aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabrice Bellard <fabrice@bellard.org>2003-12-15 14:43:44 +0000
committerFabrice Bellard <fabrice@bellard.org>2003-12-15 14:43:44 +0000
commita700a6ae8f5ac72f0c5eabb7c5f21a0e925ecc0f (patch)
tree5da9f41a1fe1a1a4aafb71ce7d5236245962611f
parent6e45e928562810f40811e30b1dc0a485cb8257ef (diff)
downloadffmpeg-a700a6ae8f5ac72f0c5eabb7c5f21a0e925ecc0f.tar.gz
moved packet output to a separate function - added the frame buffered by the decoder at EOF, if any
Originally committed as revision 2615 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r--ffmpeg.c379
1 files changed, 206 insertions, 173 deletions
diff --git a/ffmpeg.c b/ffmpeg.c
index 990ce0edff..a3f4bbdc00 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -791,6 +791,197 @@ static void print_report(AVFormatContext **output_files,
fprintf(stderr, "\n");
}
+/* pkt = NULL means EOF (needed to flush decoder buffers) */
+static int output_packet(AVInputStream *ist, int ist_index,
+ AVOutputStream **ost_table, int nb_ostreams,
+ AVPacket *pkt)
+{
+ AVFormatContext *os;
+ AVOutputStream *ost;
+ uint8_t *ptr;
+ int len, ret, i;
+ uint8_t *data_buf;
+ int data_size, got_picture;
+ AVFrame picture;
+ short samples[AVCODEC_MAX_AUDIO_FRAME_SIZE / 2];
+ void *buffer_to_free;
+
+ if (pkt && pkt->pts != AV_NOPTS_VALUE) {
+ ist->pts = pkt->pts;
+ } else {
+ ist->pts = ist->next_pts;
+ }
+
+ if (pkt == NULL) {
+ /* EOF handling */
+ ptr = NULL;
+ len = 0;
+ goto handle_eof;
+ }
+
+ len = pkt->size;
+ ptr = pkt->data;
+ while (len > 0) {
+ handle_eof:
+ /* decode the packet if needed */
+ data_buf = NULL; /* fail safe */
+ data_size = 0;
+ if (ist->decoding_needed) {
+ switch(ist->st->codec.codec_type) {
+ case CODEC_TYPE_AUDIO:
+ /* XXX: could avoid copy if PCM 16 bits with same
+ endianness as CPU */
+ ret = avcodec_decode_audio(&ist->st->codec, samples, &data_size,
+ ptr, len);
+ if (ret < 0)
+ goto fail_decode;
+ ptr += ret;
+ len -= ret;
+ /* Some bug in mpeg audio decoder gives */
+ /* data_size < 0, it seems they are overflows */
+ if (data_size <= 0) {
+ /* no audio frame */
+ continue;
+ }
+ data_buf = (uint8_t *)samples;
+ ist->next_pts += ((int64_t)AV_TIME_BASE * data_size) /
+ (2 * ist->st->codec.channels);
+ break;
+ case CODEC_TYPE_VIDEO:
+ data_size = (ist->st->codec.width * ist->st->codec.height * 3) / 2;
+ /* XXX: allocate picture correctly */
+ memset(&picture, 0, sizeof(picture));
+ ret = avcodec_decode_video(&ist->st->codec,
+ &picture, &got_picture, ptr, len);
+ ist->st->quality= picture.quality;
+ if (ret < 0)
+ goto fail_decode;
+ if (!got_picture) {
+ /* no picture yet */
+ goto discard_packet;
+ }
+ if (ist->st->codec.frame_rate_base != 0) {
+ ist->next_pts += ((int64_t)AV_TIME_BASE *
+ ist->st->codec.frame_rate_base) /
+ ist->st->codec.frame_rate;
+ }
+ len = 0;
+ break;
+ default:
+ goto fail_decode;
+ }
+ } else {
+ data_buf = ptr;
+ data_size = len;
+ ret = len;
+ len = 0;
+ }
+
+ buffer_to_free = NULL;
+ if (ist->st->codec.codec_type == CODEC_TYPE_VIDEO) {
+ pre_process_video_frame(ist, (AVPicture *)&picture,
+ &buffer_to_free);
+ }
+
+ /* frame rate emulation */
+ if (ist->st->codec.rate_emu) {
+ int64_t pts = av_rescale((int64_t) ist->frame * ist->st->codec.frame_rate_base, 1000000, ist->st->codec.frame_rate);
+ int64_t now = av_gettime() - ist->start;
+ if (pts > now)
+ usleep(pts - now);
+
+ ist->frame++;
+ }
+
+#if 0
+ /* mpeg PTS deordering : if it is a P or I frame, the PTS
+ is the one of the next displayed one */
+ /* XXX: add mpeg4 too ? */
+ if (ist->st->codec.codec_id == CODEC_ID_MPEG1VIDEO) {
+ if (ist->st->codec.pict_type != B_TYPE) {
+ int64_t tmp;
+ tmp = ist->last_ip_pts;
+ ist->last_ip_pts = ist->frac_pts.val;
+ ist->frac_pts.val = tmp;
+ }
+ }
+#endif
+ /* if output time reached then transcode raw format,
+ encode packets and output them */
+ if (start_time == 0 || ist->pts >= start_time)
+ for(i=0;i<nb_ostreams;i++) {
+ int frame_size;
+
+ ost = ost_table[i];
+ if (ost->source_index == ist_index) {
+ os = output_files[ost->file_index];
+
+#if 0
+ printf("%d: got pts=%0.3f %0.3f\n", i,
+ (double)pkt->pts / AV_TIME_BASE,
+ ((double)ist->pts / AV_TIME_BASE) -
+ ((double)ost->st->pts.val * os->pts_num / os->pts_den));
+#endif
+ /* set the input output pts pairs */
+ ost->sync_ipts = (double)ist->pts / AV_TIME_BASE;
+ /* XXX: take into account the various fifos,
+ in particular for audio */
+ ost->sync_opts = ost->st->pts.val;
+ //printf("ipts=%lld sync_ipts=%f sync_opts=%lld pts.val=%lld pkt->pts=%lld\n", ist->pts, ost->sync_ipts, ost->sync_opts, ost->st->pts.val, pkt->pts);
+
+ if (ost->encoding_needed) {
+ switch(ost->st->codec.codec_type) {
+ case CODEC_TYPE_AUDIO:
+ do_audio_out(os, ost, ist, data_buf, data_size);
+ break;
+ case CODEC_TYPE_VIDEO:
+ /* find an audio stream for synchro */
+ {
+ int i;
+ AVOutputStream *audio_sync, *ost1;
+ audio_sync = NULL;
+ for(i=0;i<nb_ostreams;i++) {
+ ost1 = ost_table[i];
+ if (ost1->file_index == ost->file_index &&
+ ost1->st->codec.codec_type == CODEC_TYPE_AUDIO) {
+ audio_sync = ost1;
+ break;
+ }
+ }
+
+ do_video_out(os, ost, ist, &picture, &frame_size, audio_sync);
+ if (do_vstats && frame_size)
+ do_video_stats(os, ost, frame_size);
+ }
+ break;
+ default:
+ av_abort();
+ }
+ } else {
+ AVFrame avframe;
+
+ /* no reencoding needed : output the packet directly */
+ /* force the input stream PTS */
+
+ memset(&avframe, 0, sizeof(AVFrame));
+ ost->st->codec.coded_frame= &avframe;
+ avframe.key_frame = pkt->flags & PKT_FLAG_KEY;
+
+ av_write_frame(os, ost->index, data_buf, data_size);
+ ost->st->codec.frame_number++;
+ ost->frame_number++;
+ }
+ }
+ }
+ av_free(buffer_to_free);
+ }
+ discard_packet:
+ return 0;
+ fail_decode:
+ return -1;
+}
+
+
/*
* The following code is the main loop of the file converter
*/
@@ -1191,13 +1382,6 @@ static int av_encode(AVFormatContext **output_files,
for(; received_sigterm == 0;) {
int file_index, ist_index;
AVPacket pkt;
- uint8_t *ptr;
- int len;
- uint8_t *data_buf;
- int data_size, got_picture;
- AVFrame picture;
- short samples[AVCODEC_MAX_AUDIO_FRAME_SIZE / 2];
- void *buffer_to_free;
double pts_min;
redo:
@@ -1258,179 +1442,28 @@ static int av_encode(AVFormatContext **output_files,
goto discard_packet;
//fprintf(stderr,"read #%d.%d size=%d\n", ist->file_index, ist->index, pkt.size);
-
- if (pkt.pts != AV_NOPTS_VALUE) {
- ist->pts = pkt.pts;
- } else {
- ist->pts = ist->next_pts;
- }
-
- len = pkt.size;
- ptr = pkt.data;
- while (len > 0) {
- /* decode the packet if needed */
- data_buf = NULL; /* fail safe */
- data_size = 0;
- if (ist->decoding_needed) {
- switch(ist->st->codec.codec_type) {
- case CODEC_TYPE_AUDIO:
- /* XXX: could avoid copy if PCM 16 bits with same
- endianness as CPU */
- ret = avcodec_decode_audio(&ist->st->codec, samples, &data_size,
- ptr, len);
- if (ret < 0)
- goto fail_decode;
- ptr += ret;
- len -= ret;
- /* Some bug in mpeg audio decoder gives */
- /* data_size < 0, it seems they are overflows */
- if (data_size <= 0) {
- /* no audio frame */
- continue;
- }
- data_buf = (uint8_t *)samples;
- ist->next_pts += ((int64_t)AV_TIME_BASE * data_size) /
- (2 * ist->st->codec.channels);
- break;
- case CODEC_TYPE_VIDEO:
- data_size = (ist->st->codec.width * ist->st->codec.height * 3) / 2;
- /* XXX: allocate picture correctly */
- memset(&picture, 0, sizeof(picture));
- ret = avcodec_decode_video(&ist->st->codec,
- &picture, &got_picture, ptr, len);
- ist->st->quality= picture.quality;
- if (ret < 0) {
- fail_decode:
- fprintf(stderr, "Error while decoding stream #%d.%d\n",
- ist->file_index, ist->index);
- av_free_packet(&pkt);
- goto redo;
- }
- if (!got_picture) {
- /* no picture yet */
- goto discard_packet;
- }
- if (ist->st->codec.frame_rate_base != 0) {
- ist->next_pts += ((int64_t)AV_TIME_BASE *
- ist->st->codec.frame_rate_base) /
- ist->st->codec.frame_rate;
- }
- len = 0;
- break;
- default:
- goto fail_decode;
- }
- } else {
- data_buf = ptr;
- data_size = len;
- ret = len;
- len = 0;
- }
-
- buffer_to_free = NULL;
- if (ist->st->codec.codec_type == CODEC_TYPE_VIDEO) {
- pre_process_video_frame(ist, (AVPicture *)&picture,
- &buffer_to_free);
- }
-
- /* frame rate emulation */
- if (ist->st->codec.rate_emu) {
- int64_t pts = av_rescale((int64_t) ist->frame * ist->st->codec.frame_rate_base, 1000000, ist->st->codec.frame_rate);
- int64_t now = av_gettime() - ist->start;
- if (pts > now)
- usleep(pts - now);
-
- ist->frame++;
- }
-
-#if 0
- /* mpeg PTS deordering : if it is a P or I frame, the PTS
- is the one of the next displayed one */
- /* XXX: add mpeg4 too ? */
- if (ist->st->codec.codec_id == CODEC_ID_MPEG1VIDEO) {
- if (ist->st->codec.pict_type != B_TYPE) {
- int64_t tmp;
- tmp = ist->last_ip_pts;
- ist->last_ip_pts = ist->frac_pts.val;
- ist->frac_pts.val = tmp;
- }
- }
-#endif
- /* if output time reached then transcode raw format,
- encode packets and output them */
- if (start_time == 0 || ist->pts >= start_time)
- for(i=0;i<nb_ostreams;i++) {
- int frame_size;
-
- ost = ost_table[i];
- if (ost->source_index == ist_index) {
- os = output_files[ost->file_index];
-
-#if 0
- printf("%d: got pts=%0.3f %0.3f\n", i,
- (double)pkt.pts / AV_TIME_BASE,
- ((double)ist->pts / AV_TIME_BASE) -
- ((double)ost->st->pts.val * os->pts_num / os->pts_den));
-#endif
- /* set the input output pts pairs */
- ost->sync_ipts = (double)ist->pts / AV_TIME_BASE;
- /* XXX: take into account the various fifos,
- in particular for audio */
- ost->sync_opts = ost->st->pts.val;
- //printf("ipts=%lld sync_ipts=%f sync_opts=%lld pts.val=%lld pkt.pts=%lld\n", ist->pts, ost->sync_ipts, ost->sync_opts, ost->st->pts.val, pkt.pts);
-
- if (ost->encoding_needed) {
- switch(ost->st->codec.codec_type) {
- case CODEC_TYPE_AUDIO:
- do_audio_out(os, ost, ist, data_buf, data_size);
- break;
- case CODEC_TYPE_VIDEO:
- /* find an audio stream for synchro */
- {
- int i;
- AVOutputStream *audio_sync, *ost1;
- audio_sync = NULL;
- for(i=0;i<nb_ostreams;i++) {
- ost1 = ost_table[i];
- if (ost1->file_index == ost->file_index &&
- ost1->st->codec.codec_type == CODEC_TYPE_AUDIO) {
- audio_sync = ost1;
- break;
- }
- }
-
- do_video_out(os, ost, ist, &picture, &frame_size, audio_sync);
- if (do_vstats && frame_size)
- do_video_stats(os, ost, frame_size);
- }
- break;
- default:
- av_abort();
- }
- } else {
- AVFrame avframe;
-
- /* no reencoding needed : output the packet directly */
- /* force the input stream PTS */
-
- memset(&avframe, 0, sizeof(AVFrame));
- ost->st->codec.coded_frame= &avframe;
- avframe.key_frame = pkt.flags & PKT_FLAG_KEY;
-
- av_write_frame(os, ost->index, data_buf, data_size);
- ost->st->codec.frame_number++;
- ost->frame_number++;
- }
- }
- }
- av_free(buffer_to_free);
+ if (output_packet(ist, ist_index, ost_table, nb_ostreams, &pkt) < 0) {
+ fprintf(stderr, "Error while decoding stream #%d.%d\n",
+ ist->file_index, ist->index);
+ av_free_packet(&pkt);
+ goto redo;
}
+
discard_packet:
av_free_packet(&pkt);
/* dump report by using the output first video and audio streams */
print_report(output_files, ost_table, nb_ostreams, 0);
}
+
+ /* at the end of stream, we must flush the decoder buffers */
+ for(i=0;i<nb_istreams;i++) {
+ ist = ist_table[i];
+ if (ist->decoding_needed) {
+ output_packet(ist, i, ost_table, nb_ostreams, NULL);
+ }
+ }
+
term_exit();
/* dump report by using the first video and audio streams */