|
|
|
@ -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;i<nb_ostreams;i++) { |
|
|
|
|
ost = &ost_table[i]; |
|
|
|
|
if (ost->source_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; |
|
|
|
|