[FFmpeg-devel] [PATCH] '-longest' command-line argument realization
Michael N. Pritula
pritula
Wed Feb 11 16:19:48 CET 2009
Michael Niedermayer wrote:
> for what is it good to lengthen streams to a common point?
Some players stop playing when one of the streams ended. Also this
problem has been raised in FFmpeg-user mailing list:
http://lists.mplayerhq.hu/pipermail/ffmpeg-user/2007-June/009625.html
And there are number of clips with different duration of streams. For
example, clip with ending captions without any sound glued to ordinary
clip with sound.
Here is a patch with satisfacted remarks:
--- ffmpeg.c.mplayerhq 2009-02-03 10:17:49.000000000 +0300
+++ ffmpeg.c 2009-02-11 17:47:07.000000000 +0300
@@ -192,6 +192,7 @@
static float audio_drift_threshold= 0.1;
static int copy_ts= 0;
static int opt_shortest = 0;
+static int opt_longest = 0;
static int video_global_header = 0;
static char *vstats_filename;
static FILE *vstats_file;
@@ -286,6 +287,7 @@
is not defined */
int64_t pts; /* current pts */
int is_start; /* is 1 at the start and after a
discontinuity */
+ AVFrame last_picture;
} AVInputStream;
typedef struct AVInputFile {
@@ -1260,6 +1262,7 @@
/* no picture yet */
goto discard_packet;
}
+ ist->last_picture = picture;
if (ist->st->codec->time_base.num != 0) {
ist->next_pts += ((int64_t)AV_TIME_BASE *
ist->st->codec->time_base.num) /
@@ -2177,6 +2180,111 @@
}
}
+ if (opt_longest) {
+ double opts_max = -1e100;
+ int istreams_needed[MAX_STREAMS];
+ int nb_istreams_needed = 0;
+ for(i=0;i<nb_ostreams;i++) {
+ double opts;
+ ost = ost_table[i];
+ if(ost->st->codec->codec_type == CODEC_TYPE_VIDEO) {
+ opts = ost->sync_opts * av_q2d(ost->st->codec->time_base);
+ } else {
+ opts = ost->st->pts.val * av_q2d(ost->st->time_base);
+ }
+ opts_max = FFMAX(opts_max, opts);
+ }
+ for(i=0;i<nb_ostreams;i++) {
+ if ((ost_table[i]->st->codec->codec_type ==
CODEC_TYPE_VIDEO || ost_table[i]->st->codec->codec_type ==
CODEC_TYPE_AUDIO) && ost_table[i]->encoding_needed &&
ist_table[ost_table[i]->source_index]->decoding_needed) {
+ double opts, granularity;
+ ost = ost_table[i];
+ os = output_files[ost->file_index];
+ ist = ist_table[ost->source_index];
+ if(ost->st->codec->codec_type == CODEC_TYPE_VIDEO) {
+ opts = ost->sync_opts *
av_q2d(ost->st->codec->time_base);
+ granularity = av_q2d(ost->st->codec->time_base);
+ } else {
+ opts = ost->st->pts.val * av_q2d(ost->st->time_base);
+ granularity = av_q2d(ost->st->time_base);
+ }
+ granularity = FFMAX(0, granularity);
+ if (opts + granularity / 2.0 < opts_max) {
+ int j;
+ for(j=0;j<nb_istreams_needed;j++)
+ if (ost->source_index == istreams_needed[j])
+ break;
+ istreams_needed[j] = ost->source_index;
+ if (j >= nb_istreams_needed)
+ nb_istreams_needed = j + 1;
+ }
+ }
+ }
+ for(i=0;i<nb_istreams_needed;i++) {
+ int continue_flag = 0;
+ double input_granularity = 0;
+ ist = ist_table[istreams_needed[i]];
+ switch (ist->st->codec->codec_type) {
+ case CODEC_TYPE_VIDEO:
+ input_granularity = av_q2d(ist->st->codec->time_base);
+ break;
+ default:
+ input_granularity = av_q2d(ist->st->time_base);
+ break;
+ }
+ do {
+ int j;
+ continue_flag = 0;
+ for(j=0;j<nb_ostreams;j++) {
+ if (ost_table[j]->encoding_needed &&
ost_table[j]->source_index == istreams_needed[i]) {
+ double opts = 0;
+ double granularity = 0;
+ ost = ost_table[j];
+ os = output_files[ost->file_index];
+ switch (ost->st->codec->codec_type) {
+ case CODEC_TYPE_AUDIO: {
+ uint8_t *samples = NULL;
+ int samples_size = 0;
+ opts = ost->st->pts.val *
av_q2d(ost->st->time_base);
+ granularity = av_q2d(ost->st->time_base);
+ while (opts + granularity / 2.0 < opts_max) {
+ int count_to_write =
(int)(av_get_bits_per_sample_format(ist->st->codec->sample_fmt) / 8 *
ist->st->codec->channels * FFMAX(1, ist->st->codec->sample_rate *
(opts_max-opts)));
+ while (count_to_write > 0) {
+ int data_size =
FFMIN(AVCODEC_MAX_AUDIO_FRAME_SIZE, count_to_write);
+ if (samples_size < data_size) {
+ av_free(samples);
+ samples_size = data_size;
+ samples = av_mallocz(samples_size);
+ }
+ do_audio_out(os, ost, ist, samples,
data_size);
+ count_to_write -= data_size;
+ }
+ opts = ost->st->pts.val *
av_q2d(ost->st->time_base);
+ }
+ av_free(samples);
+ break;
+ }
+ case CODEC_TYPE_VIDEO:
+ opts = ost->sync_opts *
av_q2d(ost->st->codec->time_base);
+ granularity =
av_q2d(ost->st->codec->time_base);
+ if (opts < opts_max) {
+ int frame_size = 0;
+ do_video_out(os, ost, ist,
&ist->last_picture, &frame_size);
+ if (vstats_filename && frame_size)
+ do_video_stats(os, ost, frame_size);
+ opts = ost->sync_opts *
av_q2d(ost->st->codec->time_base);
+ continue_flag = opts < opts_max;
+ }
+ break;
+ }
+ }
+ }
+ if (continue_flag) {
+ ist->pts += input_granularity * AV_TIME_BASE;
+ }
+ } while (continue_flag);
+ }
+ }
+
term_exit();
/* write the trailer if needed and close file */
@@ -3794,6 +3902,7 @@
{ "vglobal", HAS_ARG | OPT_INT | OPT_EXPERT,
{(void*)&video_global_header}, "video global header storage type", "" },
{ "copyts", OPT_BOOL | OPT_EXPERT, {(void*)©_ts}, "copy
timestamps" },
{ "shortest", OPT_BOOL | OPT_EXPERT, {(void*)&opt_shortest},
"finish encoding within shortest input" }, //
+ { "longest", OPT_BOOL | OPT_EXPERT, {(void*)&opt_longest}, "append
shorter streams to longest duration" },
{ "dts_delta_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT,
{(void*)&dts_delta_threshold}, "timestamp discontinuity delta
threshold", "threshold" },
{ "programid", HAS_ARG | OPT_INT | OPT_EXPERT,
{(void*)&opt_programid}, "desired program number", "" },
{ "xerror", OPT_BOOL, {(void*)&exit_on_error}, "exit on error",
"error" },
--- Changelog.mplayerhq 2009-02-03 10:17:49.000000000 +0300
+++ Changelog 2009-02-11 17:58:35.000000000 +0300
@@ -146,6 +146,7 @@
- hybrid WavPack support
- R3D REDCODE demuxer
- ALSA support for playback and record
+- '-longest' command line argument support
version 0.4.9-pre1:
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ffmpeg.longest.patch
Type: text/x-patch
Size: 7620 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20090211/8af87c8c/attachment.bin>
More information about the ffmpeg-devel
mailing list