From fc97f8e0e2146d9a23092b148de9124de2424446 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 9 Aug 2012 18:04:17 +0200 Subject: ffmpeg: factorize process_input() out Based-on: commit 0c00fd80ee4791bd70b634084307fc9f179e0412 Author: Anton Khirnov Signed-off-by: Michael Niedermayer --- ffmpeg.c | 329 ++++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 178 insertions(+), 151 deletions(-) (limited to 'ffmpeg.c') diff --git a/ffmpeg.c b/ffmpeg.c index bb69a347f8..8c8e01de04 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -2691,13 +2691,184 @@ static void reset_eagain(void) input_files[i]->eagain = 0; } +/** + * @return + * - 0 -- one packet was read and processed + * - AVERROR(EAGAIN) -- no packets were available for selected file, + * this function should be called again + * - AVERROR_EOF -- this function should not be called again + */ +static int process_input(void) +{ + InputFile *ifile; + AVFormatContext *is; + InputStream *ist; + AVPacket pkt; + int ret, i, j; + int file_index; + + /* select the stream that we must read now */ + file_index = select_input_file(); + /* if none, if is finished */ + if (file_index == -2) { + poll_filters() ; + return AVERROR(EAGAIN); + } + if (file_index < 0) { + if (got_eagain()) { + reset_eagain(); + av_usleep(10000); + return AVERROR(EAGAIN); + } + av_log(NULL, AV_LOG_VERBOSE, "No more inputs to read from, finishing.\n"); + return AVERROR_EOF; + } + ifile = input_files[file_index]; + + is = ifile->ctx; + ret = get_input_packet(ifile, &pkt); + + if (ret == AVERROR(EAGAIN)) { + ifile->eagain = 1; + return ret; + } + if (ret < 0) { + if (ret != AVERROR_EOF) { + print_error(is->filename, ret); + if (exit_on_error) + exit_program(1); + } + ifile->eof_reached = 1; + + for (i = 0; i < ifile->nb_streams; i++) { + ist = input_streams[ifile->ist_index + i]; + if (ist->decoding_needed) + output_packet(ist, NULL); + poll_filters(); + } + + if (opt_shortest) + return AVERROR_EOF; + else + return AVERROR(EAGAIN); + } + + reset_eagain(); + + if (do_pkt_dump) { + av_pkt_dump_log2(NULL, AV_LOG_DEBUG, &pkt, do_hex_dump, + is->streams[pkt.stream_index]); + } + /* the following test is needed in case new streams appear + dynamically in stream : we ignore them */ + if (pkt.stream_index >= ifile->nb_streams) { + report_new_stream(file_index, &pkt); + goto discard_packet; + } + + ist = input_streams[ifile->ist_index + pkt.stream_index]; + if (ist->discard) + goto discard_packet; + + if(!ist->wrap_correction_done && input_files[file_index]->ctx->start_time != AV_NOPTS_VALUE && ist->st->pts_wrap_bits < 64){ + uint64_t stime = av_rescale_q(input_files[file_index]->ctx->start_time, AV_TIME_BASE_Q, ist->st->time_base); + uint64_t stime2= stime + (1LL<st->pts_wrap_bits); + ist->wrap_correction_done = 1; + if(pkt.dts != AV_NOPTS_VALUE && pkt.dts > stime && pkt.dts - stime > stime2 - pkt.dts) { + pkt.dts -= 1LL<st->pts_wrap_bits; + ist->wrap_correction_done = 0; + } + if(pkt.pts != AV_NOPTS_VALUE && pkt.pts > stime && pkt.pts - stime > stime2 - pkt.pts) { + pkt.pts -= 1LL<st->pts_wrap_bits; + ist->wrap_correction_done = 0; + } + } + + if (pkt.dts != AV_NOPTS_VALUE) + pkt.dts += av_rescale_q(ifile->ts_offset, AV_TIME_BASE_Q, ist->st->time_base); + if (pkt.pts != AV_NOPTS_VALUE) + pkt.pts += av_rescale_q(ifile->ts_offset, AV_TIME_BASE_Q, ist->st->time_base); + + if (pkt.pts != AV_NOPTS_VALUE) + pkt.pts *= ist->ts_scale; + if (pkt.dts != AV_NOPTS_VALUE) + pkt.dts *= ist->ts_scale; + + if (debug_ts) { + av_log(NULL, AV_LOG_INFO, "demuxer -> ist_index:%d type:%s " + "next_dts:%s next_dts_time:%s next_pts:%s next_pts_time:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s off:%"PRId64"\n", + ifile->ist_index + pkt.stream_index, av_get_media_type_string(ist->st->codec->codec_type), + av_ts2str(ist->next_dts), av_ts2timestr(ist->next_dts, &AV_TIME_BASE_Q), + av_ts2str(ist->next_pts), av_ts2timestr(ist->next_pts, &AV_TIME_BASE_Q), + av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ist->st->time_base), + av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ist->st->time_base), + input_files[ist->file_index]->ts_offset); + } + + if (pkt.dts != AV_NOPTS_VALUE && ist->next_dts != AV_NOPTS_VALUE && + !copy_ts) { + int64_t pkt_dts = av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q); + int64_t delta = pkt_dts - ist->next_dts; + if (is->iformat->flags & AVFMT_TS_DISCONT) { + if(delta < -1LL*dts_delta_threshold*AV_TIME_BASE || + (delta > 1LL*dts_delta_threshold*AV_TIME_BASE && + ist->st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) || + pkt_dts+1pts){ + ifile->ts_offset -= delta; + av_log(NULL, AV_LOG_DEBUG, + "timestamp discontinuity %"PRId64", new offset= %"PRId64"\n", + delta, ifile->ts_offset); + pkt.dts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); + if (pkt.pts != AV_NOPTS_VALUE) + pkt.pts -= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); + } + } else { + if ( delta < -1LL*dts_error_threshold*AV_TIME_BASE || + (delta > 1LL*dts_error_threshold*AV_TIME_BASE && ist->st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) || + pkt_dts+1pts){ + av_log(NULL, AV_LOG_WARNING, "DTS %"PRId64", next:%"PRId64" st:%d invalid dropping\n", pkt.dts, ist->next_dts, pkt.stream_index); + pkt.dts = AV_NOPTS_VALUE; + } + if (pkt.pts != AV_NOPTS_VALUE){ + int64_t pkt_pts = av_rescale_q(pkt.pts, ist->st->time_base, AV_TIME_BASE_Q); + delta = pkt_pts - ist->next_dts; + if ( delta < -1LL*dts_error_threshold*AV_TIME_BASE || + (delta > 1LL*dts_error_threshold*AV_TIME_BASE && ist->st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) || + pkt_pts+1pts) { + av_log(NULL, AV_LOG_WARNING, "PTS %"PRId64", next:%"PRId64" invalid dropping st:%d\n", pkt.pts, ist->next_dts, pkt.stream_index); + pkt.pts = AV_NOPTS_VALUE; + } + } + } + } + + sub2video_heartbeat(ist, pkt.pts); + + if ((ret = output_packet(ist, &pkt)) < 0 || + ((ret = poll_filters()) < 0 && ret != AVERROR_EOF)) { + char buf[128]; + av_strerror(ret, buf, sizeof(buf)); + av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d:%d: %s\n", + ist->file_index, ist->st->index, buf); + if (exit_on_error) + exit_program(1); + av_free_packet(&pkt); + return AVERROR(EAGAIN); + } + +discard_packet: + av_free_packet(&pkt); + + return 0; +} + /* * The following code is the main loop of the file converter */ static int transcode(void) { int ret, i; - AVFormatContext *is, *os; + AVFormatContext *os; OutputStream *ost; InputStream *ist; int64_t timer_start; @@ -2718,9 +2889,6 @@ static int transcode(void) #endif while (!received_sigterm) { - InputFile *ifile; - AVPacket pkt; - int file_index; int64_t cur_time= av_gettime(); /* if 'q' pressed, exits */ @@ -2734,157 +2902,16 @@ static int transcode(void) break; } - /* select the stream that we must read now */ - file_index = select_input_file(); - /* if none, if is finished */ - if (file_index == -2) { - poll_filters() ; - continue; - } - if (file_index < 0) { - if (got_eagain()) { - reset_eagain(); - av_usleep(10000); - continue; - } - av_log(NULL, AV_LOG_VERBOSE, "No more inputs to read from, finishing.\n"); - break; - } - ifile = input_files[file_index]; - - is = ifile->ctx; - ret = get_input_packet(ifile, &pkt); - - if (ret == AVERROR(EAGAIN)) { - ifile->eagain = 1; - continue; - } + ret = process_input(); if (ret < 0) { - if (ret != AVERROR_EOF) { - print_error(is->filename, ret); - if (exit_on_error) - exit_program(1); - } - ifile->eof_reached = 1; - - for (i = 0; i < ifile->nb_streams; i++) { - ist = input_streams[ifile->ist_index + i]; - if (ist->decoding_needed) - output_packet(ist, NULL); - poll_filters(); - } - - if (opt_shortest) - break; - else + if (ret == AVERROR(EAGAIN)) continue; + if (ret == AVERROR_EOF) + break; + av_log(NULL, AV_LOG_ERROR, "Error while filtering.\n"); + break; } - reset_eagain(); - - if (do_pkt_dump) { - av_pkt_dump_log2(NULL, AV_LOG_DEBUG, &pkt, do_hex_dump, - is->streams[pkt.stream_index]); - } - /* the following test is needed in case new streams appear - dynamically in stream : we ignore them */ - if (pkt.stream_index >= ifile->nb_streams) { - report_new_stream(file_index, &pkt); - goto discard_packet; - } - - ist = input_streams[ifile->ist_index + pkt.stream_index]; - if (ist->discard) - goto discard_packet; - - if(!ist->wrap_correction_done && input_files[file_index]->ctx->start_time != AV_NOPTS_VALUE && ist->st->pts_wrap_bits < 64){ - uint64_t stime = av_rescale_q(input_files[file_index]->ctx->start_time, AV_TIME_BASE_Q, ist->st->time_base); - uint64_t stime2= stime + (1LL<st->pts_wrap_bits); - ist->wrap_correction_done = 1; - if(pkt.dts != AV_NOPTS_VALUE && pkt.dts > stime && pkt.dts - stime > stime2 - pkt.dts) { - pkt.dts -= 1LL<st->pts_wrap_bits; - ist->wrap_correction_done = 0; - } - if(pkt.pts != AV_NOPTS_VALUE && pkt.pts > stime && pkt.pts - stime > stime2 - pkt.pts) { - pkt.pts -= 1LL<st->pts_wrap_bits; - ist->wrap_correction_done = 0; - } - } - - if (pkt.dts != AV_NOPTS_VALUE) - pkt.dts += av_rescale_q(ifile->ts_offset, AV_TIME_BASE_Q, ist->st->time_base); - if (pkt.pts != AV_NOPTS_VALUE) - pkt.pts += av_rescale_q(ifile->ts_offset, AV_TIME_BASE_Q, ist->st->time_base); - - if (pkt.pts != AV_NOPTS_VALUE) - pkt.pts *= ist->ts_scale; - if (pkt.dts != AV_NOPTS_VALUE) - pkt.dts *= ist->ts_scale; - - if (debug_ts) { - av_log(NULL, AV_LOG_INFO, "demuxer -> ist_index:%d type:%s " - "next_dts:%s next_dts_time:%s next_pts:%s next_pts_time:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s off:%"PRId64"\n", - ifile->ist_index + pkt.stream_index, av_get_media_type_string(ist->st->codec->codec_type), - av_ts2str(ist->next_dts), av_ts2timestr(ist->next_dts, &AV_TIME_BASE_Q), - av_ts2str(ist->next_pts), av_ts2timestr(ist->next_pts, &AV_TIME_BASE_Q), - av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ist->st->time_base), - av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ist->st->time_base), - input_files[ist->file_index]->ts_offset); - } - - if (pkt.dts != AV_NOPTS_VALUE && ist->next_dts != AV_NOPTS_VALUE && !copy_ts) { - int64_t pkt_dts = av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q); - int64_t delta = pkt_dts - ist->next_dts; - if (is->iformat->flags & AVFMT_TS_DISCONT) { - if(delta < -1LL*dts_delta_threshold*AV_TIME_BASE || - (delta > 1LL*dts_delta_threshold*AV_TIME_BASE && - ist->st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) || - pkt_dts+1pts){ - ifile->ts_offset -= delta; - av_log(NULL, AV_LOG_DEBUG, - "timestamp discontinuity %"PRId64", new offset= %"PRId64"\n", - delta, ifile->ts_offset); - pkt.dts-= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); - if (pkt.pts != AV_NOPTS_VALUE) - pkt.pts-= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); - } - } else { - if ( delta < -1LL*dts_error_threshold*AV_TIME_BASE || - (delta > 1LL*dts_error_threshold*AV_TIME_BASE && ist->st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) || - pkt_dts+1pts){ - av_log(NULL, AV_LOG_WARNING, "DTS %"PRId64", next:%"PRId64" st:%d invalid dropping\n", pkt.dts, ist->next_dts, pkt.stream_index); - pkt.dts = AV_NOPTS_VALUE; - } - if (pkt.pts != AV_NOPTS_VALUE){ - int64_t pkt_pts = av_rescale_q(pkt.pts, ist->st->time_base, AV_TIME_BASE_Q); - delta = pkt_pts - ist->next_dts; - if ( delta < -1LL*dts_error_threshold*AV_TIME_BASE || - (delta > 1LL*dts_error_threshold*AV_TIME_BASE && ist->st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) || - pkt_pts+1pts) { - av_log(NULL, AV_LOG_WARNING, "PTS %"PRId64", next:%"PRId64" invalid dropping st:%d\n", pkt.pts, ist->next_dts, pkt.stream_index); - pkt.pts = AV_NOPTS_VALUE; - } - } - } - } - - sub2video_heartbeat(ist, pkt.pts); - - if ((ret = output_packet(ist, &pkt)) < 0 || - ((ret = poll_filters()) < 0 && ret != AVERROR_EOF)) { - char buf[128]; - av_strerror(ret, buf, sizeof(buf)); - av_log(NULL, AV_LOG_ERROR, "Error while decoding stream #%d:%d: %s\n", - ist->file_index, ist->st->index, buf); - if (exit_on_error) - exit_program(1); - av_free_packet(&pkt); - continue; - } - - discard_packet: - av_free_packet(&pkt); - /* dump report by using the output first video and audio streams */ print_report(0, timer_start, cur_time); } -- cgit v1.2.3