diff --git a/doc/ffplay-doc.texi b/doc/ffplay-doc.texi index 11794b2cd4..e0ca79d436 100644 --- a/doc/ffplay-doc.texi +++ b/doc/ffplay-doc.texi @@ -45,6 +45,8 @@ Disable audio. Disable video. @item -ss @var{pos} Seek to a given position in seconds. +@item -t @var{duration} +play seconds of audio/video @item -bytes Seek by bytes. @item -nodisp diff --git a/ffplay.c b/ffplay.c index c32710b855..93f64abe15 100644 --- a/ffplay.c +++ b/ffplay.c @@ -244,6 +244,7 @@ static int display_disable; static int show_status = 1; static int av_sync_type = AV_SYNC_AUDIO_MASTER; static int64_t start_time = AV_NOPTS_VALUE; +static int64_t duration = AV_NOPTS_VALUE; static int debug = 0; static int debug_mv = 0; static int step = 0; @@ -2360,6 +2361,7 @@ static int decode_thread(void *arg) AVPacket pkt1, *pkt = &pkt1; AVFormatParameters params, *ap = ¶ms; int eof=0; + int pkt_in_play_range = 0; ic = avformat_alloc_context(); @@ -2559,11 +2561,17 @@ static int decode_thread(void *arg) SDL_Delay(100); /* wait for user event */ continue; } - if (pkt->stream_index == is->audio_stream) { + /* check if packet is in play range specified by user, then queue, otherwise discard */ + pkt_in_play_range = duration == AV_NOPTS_VALUE || + (pkt->pts - ic->streams[pkt->stream_index]->start_time) * + av_q2d(ic->streams[pkt->stream_index]->time_base) - + (double)(start_time != AV_NOPTS_VALUE ? start_time : 0)/1000000 + <= ((double)duration/1000000); + if (pkt->stream_index == is->audio_stream && pkt_in_play_range) { packet_queue_put(&is->audioq, pkt); - } else if (pkt->stream_index == is->video_stream) { + } else if (pkt->stream_index == is->video_stream && pkt_in_play_range) { packet_queue_put(&is->videoq, pkt); - } else if (pkt->stream_index == is->subtitle_stream) { + } else if (pkt->stream_index == is->subtitle_stream && pkt_in_play_range) { packet_queue_put(&is->subtitleq, pkt); } else { av_free_packet(pkt); @@ -2971,6 +2979,12 @@ static int opt_seek(const char *opt, const char *arg) return 0; } +static int opt_duration(const char *opt, const char *arg) +{ + duration = parse_time_or_die(opt, arg, 1); + return 0; +} + static int opt_debug(const char *opt, const char *arg) { av_log_set_level(99); @@ -3005,6 +3019,7 @@ static const OptionDef options[] = { { "vst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_stream[AVMEDIA_TYPE_VIDEO]}, "select desired video stream", "stream_number" }, { "sst", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&wanted_stream[AVMEDIA_TYPE_SUBTITLE]}, "select desired subtitle stream", "stream_number" }, { "ss", HAS_ARG | OPT_FUNC2, {(void*)&opt_seek}, "seek to a given position in seconds", "pos" }, + { "t", HAS_ARG | OPT_FUNC2, {(void*)&opt_duration}, "play \"duration\" seconds of audio/video", "duration" }, { "bytes", OPT_INT | HAS_ARG, {(void*)&seek_by_bytes}, "seek by bytes 0=off 1=on -1=auto", "val" }, { "nodisp", OPT_BOOL, {(void*)&display_disable}, "disable graphical display" }, { "f", HAS_ARG, {(void*)opt_format}, "force format", "fmt" },