Commit 30bc6613 authored by Michael Niedermayer's avatar Michael Niedermayer

support fixing missing pts by parsing future frames

Originally committed as revision 4526 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent af9da83b
...@@ -211,6 +211,7 @@ static int frame_skip_cmp= FF_CMP_DCTMAX; ...@@ -211,6 +211,7 @@ static int frame_skip_cmp= FF_CMP_DCTMAX;
extern int loop_input; /* currently a hack */ extern int loop_input; /* currently a hack */
static int loop_output = AVFMT_NOOUTPUTLOOP; static int loop_output = AVFMT_NOOUTPUTLOOP;
static int gray_only = 0; static int gray_only = 0;
static int genpts = 0;
static int gop_size = 12; static int gop_size = 12;
static int intra_only = 0; static int intra_only = 0;
...@@ -3031,6 +3032,9 @@ static void opt_input_file(const char *filename) ...@@ -3031,6 +3032,9 @@ static void opt_input_file(const char *filename)
print_error(filename, err); print_error(filename, err);
exit(1); exit(1);
} }
if(genpts)
ic->flags|= AVFMT_FLAG_GENPTS;
/* If not enough info to get the stream parameters, we decode the /* If not enough info to get the stream parameters, we decode the
first frames to get it. (used in mpeg case for example) */ first frames to get it. (used in mpeg case for example) */
...@@ -4340,6 +4344,7 @@ const OptionDef options[] = { ...@@ -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" }, { "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" }, { "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" }, { "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 */ /* audio options */
{ "ab", HAS_ARG | OPT_AUDIO, {(void*)opt_audio_bitrate}, "set audio bitrate (in kbit/s)", "bitrate", }, { "ab", HAS_ARG | OPT_AUDIO, {(void*)opt_audio_bitrate}, "set audio bitrate (in kbit/s)", "bitrate", },
......
...@@ -210,6 +210,7 @@ static int step = 0; ...@@ -210,6 +210,7 @@ static int step = 0;
static int thread_count = 1; static int thread_count = 1;
static int workaround_bugs = 1; static int workaround_bugs = 1;
static int fast = 0; static int fast = 0;
static int genpts = 0;
static int lowres = 0; static int lowres = 0;
static int idct = FF_IDCT_AUTO; static int idct = FF_IDCT_AUTO;
static enum AVDiscard skip_frame= AVDISCARD_DEFAULT; static enum AVDiscard skip_frame= AVDISCARD_DEFAULT;
...@@ -1802,6 +1803,10 @@ static int decode_thread(void *arg) ...@@ -1802,6 +1803,10 @@ static int decode_thread(void *arg)
#else #else
use_play = 0; use_play = 0;
#endif #endif
if(genpts)
ic->flags |= AVFMT_FLAG_GENPTS;
if (!use_play) { if (!use_play) {
err = av_find_stream_info(ic); err = av_find_stream_info(ic);
if (err < 0) { if (err < 0) {
...@@ -2356,6 +2361,7 @@ const OptionDef options[] = { ...@@ -2356,6 +2361,7 @@ const OptionDef options[] = {
{ "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" }, { "bug", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&workaround_bugs}, "workaround bugs", "" },
{ "vismv", HAS_ARG | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" }, { "vismv", HAS_ARG | OPT_EXPERT, {(void*)opt_vismv}, "visualize motion vectors", "" },
{ "fast", OPT_BOOL | OPT_EXPERT, {(void*)&fast}, "non spec compliant optimizations", "" }, { "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}, "", "" }, { "lowres", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&lowres}, "", "" },
{ "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_loop_filter}, "", "" }, { "skiploop", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_loop_filter}, "", "" },
{ "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_frame}, "", "" }, { "skipframe", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&skip_frame}, "", "" },
......
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
extern "C" { extern "C" {
#endif #endif
#define LIBAVFORMAT_VERSION_INT ((49<<16)+(0<<8)+0) #define LIBAVFORMAT_VERSION_INT ((49<<16)+(1<<8)+0)
#define LIBAVFORMAT_VERSION 49.0.0 #define LIBAVFORMAT_VERSION 49.1.0
#define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT #define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT
#define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION) #define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION)
...@@ -332,6 +332,8 @@ typedef struct AVFormatContext { ...@@ -332,6 +332,8 @@ typedef struct AVFormatContext {
/* number of times to loop output in formats that support it */ /* number of times to loop output in formats that support it */
int loop_output; int loop_output;
int flags;
#define AVFMT_FLAG_GENPTS 0x0001 ///< generate pts if missing even if it requires parsing future frames
} AVFormatContext; } AVFormatContext;
typedef struct AVPacketList { typedef struct AVPacketList {
......
...@@ -955,16 +955,66 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt) ...@@ -955,16 +955,66 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
int av_read_frame(AVFormatContext *s, AVPacket *pkt) int av_read_frame(AVFormatContext *s, AVPacket *pkt)
{ {
AVPacketList *pktl; AVPacketList *pktl;
int eof=0;
const int genpts= s->flags & AVFMT_FLAG_GENPTS;
pktl = s->packet_buffer; for(;;){
if (pktl) { pktl = s->packet_buffer;
/* read packet from packet buffer, if there is data */ if (pktl) {
*pkt = pktl->pkt; AVPacket *next_pkt= &pktl->pkt;
s->packet_buffer = pktl->next; AVStream *st= s->streams[ next_pkt->stream_index ];
av_free(pktl);
return 0; if(genpts && next_pkt->dts != AV_NOPTS_VALUE){
} else { while(pktl && next_pkt->pts == AV_NOPTS_VALUE){
return av_read_frame_internal(s, pkt); 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);
}
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment