diff --git a/ffmpeg.c b/ffmpeg.c index fc3264aae48212548c10273c4b0cff2b6d73a115..945a81d257ab75917fbd5dd736ab6927ba8bff29 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -211,6 +211,7 @@ static int frame_skip_cmp= FF_CMP_DCTMAX; extern int loop_input; /* currently a hack */ static int loop_output = AVFMT_NOOUTPUTLOOP; static int gray_only = 0; +static int genpts = 0; static int gop_size = 12; static int intra_only = 0; @@ -3031,6 +3032,9 @@ static void opt_input_file(const char *filename) print_error(filename, err); exit(1); } + + if(genpts) + ic->flags|= AVFMT_FLAG_GENPTS; /* If not enough info to get the stream parameters, we decode the first frames to get it. (used in mpeg case for example) */ @@ -4340,6 +4344,7 @@ const OptionDef options[] = { { "skip_cmp", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)&frame_skip_cmp}, "frame skip compare function", "compare function" }, { "gray", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, { (void *)&gray_only }, "encode/decode grayscale" }, { "newvideo", OPT_VIDEO, {(void*)opt_new_video_stream}, "add a new video stream to the current output stream" }, + { "genpts", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, { (void *)&genpts }, "generate pts" }, /* audio options */ { "ab", HAS_ARG | OPT_AUDIO, {(void*)opt_audio_bitrate}, "set audio bitrate (in kbit/s)", "bitrate", }, diff --git a/ffplay.c b/ffplay.c index 60b0b208581c13f58f8a09034b14d81d15620cfe..967ad1fe5a38d7ecf6aeaf135901b314a4e1a7ca 100644 --- a/ffplay.c +++ b/ffplay.c @@ -210,6 +210,7 @@ static int step = 0; static int thread_count = 1; static int workaround_bugs = 1; static int fast = 0; +static int genpts = 0; static int lowres = 0; static int idct = FF_IDCT_AUTO; static enum AVDiscard skip_frame= AVDISCARD_DEFAULT; @@ -1802,6 +1803,10 @@ static int decode_thread(void *arg) #else use_play = 0; #endif + + if(genpts) + ic->flags |= AVFMT_FLAG_GENPTS; + if (!use_play) { err = av_find_stream_info(ic); if (err < 0) { @@ -2356,6 +2361,7 @@ const OptionDef options[] = { { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" }, { "vismv", HAS_ARG | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" }, { "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" }, + { "genpts", OPT_BOOL | OPT_EXPERT, {(void*)&genpts}, "generate pts", "" }, { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" }, { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_loop_filter}, "", "" }, { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_frame}, "", "" }, diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 136f1c0a485ee7676c374c8657c87b96158c08ce..2b3937852a926f93c9429d1456e28e8a13cabf0d 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -5,8 +5,8 @@ extern "C" { #endif -#define LIBAVFORMAT_VERSION_INT ((49<<16)+(0<<8)+0) -#define LIBAVFORMAT_VERSION 49.0.0 +#define LIBAVFORMAT_VERSION_INT ((49<<16)+(1<<8)+0) +#define LIBAVFORMAT_VERSION 49.1.0 #define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT #define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION) @@ -332,6 +332,8 @@ typedef struct AVFormatContext { /* number of times to loop output in formats that support it */ int loop_output; + int flags; +#define AVFMT_FLAG_GENPTS 0x0001 ///< generate pts if missing even if it requires parsing future frames } AVFormatContext; typedef struct AVPacketList { diff --git a/libavformat/utils.c b/libavformat/utils.c index 32a4c92dce25303687d7b673b2feb25081d62faf..5a81ee068017b08558491cf3a08c2850e8d4dadd 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -955,16 +955,66 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt) int av_read_frame(AVFormatContext *s, AVPacket *pkt) { AVPacketList *pktl; + int eof=0; + const int genpts= s->flags & AVFMT_FLAG_GENPTS; - pktl = s->packet_buffer; - if (pktl) { - /* read packet from packet buffer, if there is data */ - *pkt = pktl->pkt; - s->packet_buffer = pktl->next; - av_free(pktl); - return 0; - } else { - return av_read_frame_internal(s, pkt); + for(;;){ + pktl = s->packet_buffer; + if (pktl) { + AVPacket *next_pkt= &pktl->pkt; + AVStream *st= s->streams[ next_pkt->stream_index ]; + + if(genpts && next_pkt->dts != AV_NOPTS_VALUE){ + while(pktl && next_pkt->pts == AV_NOPTS_VALUE){ + if( pktl->pkt.stream_index == next_pkt->stream_index + && next_pkt->dts < pktl->pkt.dts + && pktl->pkt.pts != pktl->pkt.dts //not b frame + /*&& pktl->pkt.dts != AV_NOPTS_VALUE*/){ + next_pkt->pts= pktl->pkt.dts; + } + pktl= pktl->next; + } + pktl = s->packet_buffer; + } + + if( next_pkt->pts != AV_NOPTS_VALUE + || next_pkt->dts == AV_NOPTS_VALUE + || !genpts || eof){ + /* read packet from packet buffer, if there is data */ + *pkt = *next_pkt; + s->packet_buffer = pktl->next; + av_free(pktl); + return 0; + } + } + if(genpts){ + AVPacketList **plast_pktl= &s->packet_buffer; + int ret= av_read_frame_internal(s, pkt); + if(ret<0){ + if(pktl && ret != -EAGAIN){ + eof=1; + continue; + }else + return ret; + } + + /* duplicate the packet */ + if (av_dup_packet(pkt) < 0) + return AVERROR_NOMEM; + + while(*plast_pktl) plast_pktl= &(*plast_pktl)->next; //FIXME maybe maintain pointer to the last? + + pktl = av_mallocz(sizeof(AVPacketList)); + if (!pktl) + return AVERROR_NOMEM; + + /* add the packet in the buffered packet list */ + *plast_pktl = pktl; + pktl->pkt= *pkt; + }else{ + assert(!s->packet_buffer); + return av_read_frame_internal(s, pkt); + } } }