diff --git a/avconv.c b/avconv.c index fb0871743b..432f5d6197 100644 --- a/avconv.c +++ b/avconv.c @@ -1396,6 +1396,93 @@ static void generate_silence(uint8_t* buf, enum AVSampleFormat sample_fmt, size_ memset(buf, fill_char, size); } +static void flush_encoders(int ist_index, OutputStream *ost_table, int nb_ostreams) +{ + int i, ret; + + for (i = 0; i < nb_ostreams; i++) { + OutputStream *ost = &ost_table[i]; + + if (ost->source_index == ist_index) { + AVCodecContext *enc = ost->st->codec; + AVFormatContext *os = output_files[ost->file_index].ctx; + + if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO && enc->frame_size <=1) + continue; + if(ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && (os->oformat->flags & AVFMT_RAWPICTURE)) + continue; + + if (ost->encoding_needed) { + for(;;) { + AVPacket pkt; + int fifo_bytes; + av_init_packet(&pkt); + pkt.stream_index= ost->index; + + switch (ost->st->codec->codec_type) { + case AVMEDIA_TYPE_AUDIO: + fifo_bytes = av_fifo_size(ost->fifo); + ret = 0; + /* encode any samples remaining in fifo */ + if (fifo_bytes > 0) { + int osize = av_get_bytes_per_sample(enc->sample_fmt); + int fs_tmp = enc->frame_size; + + av_fifo_generic_read(ost->fifo, audio_buf, fifo_bytes, NULL); + if (enc->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) { + enc->frame_size = fifo_bytes / (osize * enc->channels); + } else { /* pad */ + int frame_bytes = enc->frame_size*osize*enc->channels; + if (allocated_audio_buf_size < frame_bytes) + exit_program(1); + generate_silence(audio_buf+fifo_bytes, enc->sample_fmt, frame_bytes - fifo_bytes); + } + + ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, (short *)audio_buf); + pkt.duration = av_rescale((int64_t)enc->frame_size*ost->st->time_base.den, + ost->st->time_base.num, enc->sample_rate); + enc->frame_size = fs_tmp; + } + if (ret <= 0) { + ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, NULL); + } + if (ret < 0) { + fprintf(stderr, "Audio encoding failed\n"); + exit_program(1); + } + audio_size += ret; + pkt.flags |= AV_PKT_FLAG_KEY; + break; + case AVMEDIA_TYPE_VIDEO: + ret = avcodec_encode_video(enc, bit_buffer, bit_buffer_size, NULL); + if (ret < 0) { + fprintf(stderr, "Video encoding failed\n"); + exit_program(1); + } + video_size += ret; + if(enc->coded_frame && enc->coded_frame->key_frame) + pkt.flags |= AV_PKT_FLAG_KEY; + if (ost->logfile && enc->stats_out) { + fprintf(ost->logfile, "%s", enc->stats_out); + } + break; + default: + ret=-1; + } + + if (ret <= 0) + break; + pkt.data = bit_buffer; + pkt.size = ret; + if (enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE) + pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base); + write_frame(os, &pkt, ost->st->codec, ost->bitstream_filters); + } + } + } + } +} + /* pkt = NULL means EOF (needed to flush decoder buffers) */ static int output_packet(InputStream *ist, int ist_index, OutputStream *ost_table, int nb_ostreams, @@ -1713,87 +1800,7 @@ static int output_packet(InputStream *ist, int ist_index, discard_packet: if (pkt == NULL) { /* EOF handling */ - - for(i=0;isource_index == ist_index) { - AVCodecContext *enc= ost->st->codec; - os = output_files[ost->file_index].ctx; - - if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO && enc->frame_size <=1) - continue; - if(ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && (os->oformat->flags & AVFMT_RAWPICTURE)) - continue; - - if (ost->encoding_needed) { - for(;;) { - AVPacket pkt; - int fifo_bytes; - av_init_packet(&pkt); - pkt.stream_index= ost->index; - - switch(ost->st->codec->codec_type) { - case AVMEDIA_TYPE_AUDIO: - fifo_bytes = av_fifo_size(ost->fifo); - ret = 0; - /* encode any samples remaining in fifo */ - if (fifo_bytes > 0) { - int osize = av_get_bytes_per_sample(enc->sample_fmt); - int fs_tmp = enc->frame_size; - - av_fifo_generic_read(ost->fifo, audio_buf, fifo_bytes, NULL); - if (enc->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) { - enc->frame_size = fifo_bytes / (osize * enc->channels); - } else { /* pad */ - int frame_bytes = enc->frame_size*osize*enc->channels; - if (allocated_audio_buf_size < frame_bytes) - exit_program(1); - generate_silence(audio_buf+fifo_bytes, enc->sample_fmt, frame_bytes - fifo_bytes); - } - - ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, (short *)audio_buf); - pkt.duration = av_rescale((int64_t)enc->frame_size*ost->st->time_base.den, - ost->st->time_base.num, enc->sample_rate); - enc->frame_size = fs_tmp; - } - if(ret <= 0) { - ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, NULL); - } - if (ret < 0) { - fprintf(stderr, "Audio encoding failed\n"); - exit_program(1); - } - audio_size += ret; - pkt.flags |= AV_PKT_FLAG_KEY; - break; - case AVMEDIA_TYPE_VIDEO: - ret = avcodec_encode_video(enc, bit_buffer, bit_buffer_size, NULL); - if (ret < 0) { - fprintf(stderr, "Video encoding failed\n"); - exit_program(1); - } - video_size += ret; - if(enc->coded_frame && enc->coded_frame->key_frame) - pkt.flags |= AV_PKT_FLAG_KEY; - if (ost->logfile && enc->stats_out) { - fprintf(ost->logfile, "%s", enc->stats_out); - } - break; - default: - ret=-1; - } - - if(ret<=0) - break; - pkt.data= bit_buffer; - pkt.size= ret; - if(enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE) - pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base); - write_frame(os, &pkt, ost->st->codec, ost->bitstream_filters); - } - } - } - } + flush_encoders(ist_index, ost_table, nb_ostreams); } return 0;