support fixing missing pts by parsing future frames
Originally committed as revision 4526 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
af9da83b0e
commit
30bc6613fe
4 changed files with 74 additions and 11 deletions
5
ffmpeg.c
5
ffmpeg.c
|
@ -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;
|
||||||
|
@ -3032,6 +3033,9 @@ static void opt_input_file(const char *filename)
|
||||||
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) */
|
||||||
ret = av_find_stream_info(ic);
|
ret = av_find_stream_info(ic);
|
||||||
|
@ -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", },
|
||||||
|
|
6
ffplay.c
6
ffplay.c
|
@ -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)
|
||||||
#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[] = {
|
||||||
{ "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 @@
|
||||||
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 {
|
||||||
/* 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,17 +955,67 @@ 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;
|
||||||
|
|
||||||
|
for(;;){
|
||||||
pktl = s->packet_buffer;
|
pktl = s->packet_buffer;
|
||||||
if (pktl) {
|
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 */
|
/* read packet from packet buffer, if there is data */
|
||||||
*pkt = pktl->pkt;
|
*pkt = *next_pkt;
|
||||||
s->packet_buffer = pktl->next;
|
s->packet_buffer = pktl->next;
|
||||||
av_free(pktl);
|
av_free(pktl);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
}
|
||||||
|
}
|
||||||
|
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);
|
return av_read_frame_internal(s, pkt);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX: suppress the packet queue */
|
/* XXX: suppress the packet queue */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue