Browse code

sync output stream against any input stream (extension of map) patch by (Wolfram Gloger: wmglo, dent med uni-muenchen de)

Originally committed as revision 4308 to svn://svn.ffmpeg.org/ffmpeg/trunk

Wolfram Gloger authored on 2005/05/26 17:59:05
Showing 1 changed files
... ...
@@ -52,6 +52,8 @@
52 52
 typedef struct AVStreamMap {
53 53
     int file_index;
54 54
     int stream_index;
55
+    int sync_file_index;
56
+    int sync_stream_index;
55 57
 } AVStreamMap;
56 58
 
57 59
 /** select an input file for an output file */
... ...
@@ -277,6 +279,8 @@ static int pgmyuv_compatibility_hack=0;
277 277
 
278 278
 #define DEFAULT_PASS_LOGFILENAME "ffmpeg2pass"
279 279
 
280
+struct AVInputStream;
281
+
280 282
 typedef struct AVOutputStream {
281 283
     int file_index;          /* file index */
282 284
     int index;               /* stream index in the output file */
... ...
@@ -286,7 +290,8 @@ typedef struct AVOutputStream {
286 286
     int frame_number;
287 287
     /* input pts and corresponding output pts
288 288
        for A/V sync */
289
-    double sync_ipts;        /* dts from the AVPacket of the demuxer in second units */
289
+    //double sync_ipts;        /* dts from the AVPacket of the demuxer in second units */
290
+    struct AVInputStream *sync_ist; /* input stream to sync against */
290 291
     int64_t sync_opts;       /* output frame counter, could be changed to some true timestamp */ //FIXME look at frame_number
291 292
     /* video only */
292 293
     int video_resample;      /* video_resample and video_crop are mutually exclusive */
... ...
@@ -456,6 +461,13 @@ static int read_ffserver_streams(AVFormatContext *s, const char *filename)
456 456
     return 0;
457 457
 }
458 458
 
459
+static double
460
+get_sync_ipts(const AVOutputStream *ost)
461
+{
462
+    const AVInputStream *ist = ost->sync_ist;
463
+    return (double)(ist->pts + input_files_ts_offset[ist->file_index] - start_time)/AV_TIME_BASE;
464
+}
465
+
459 466
 #define MAX_AUDIO_PACKET_SIZE (128 * 1024)
460 467
 
461 468
 static void do_audio_out(AVFormatContext *s, 
... ...
@@ -480,7 +492,7 @@ static void do_audio_out(AVFormatContext *s,
480 480
         return;               /* Should signal an error ! */
481 481
 
482 482
     if(audio_sync_method){
483
-        double delta = ost->sync_ipts * enc->sample_rate - ost->sync_opts 
483
+        double delta = get_sync_ipts(ost) * enc->sample_rate - ost->sync_opts 
484 484
                 - fifo_size(&ost->fifo, ost->fifo.rptr)/(ost->st->codec.channels * 2);
485 485
         double idelta= delta*ist->st->codec.sample_rate / enc->sample_rate;
486 486
         int byte_delta= ((int)idelta)*2*ist->st->codec.channels;
... ...
@@ -518,12 +530,12 @@ static void do_audio_out(AVFormatContext *s,
518 518
                 assert(ost->audio_resample);
519 519
                 if(verbose > 2)
520 520
                     fprintf(stderr, "compensating audio timestamp drift:%f compensation:%d in:%d\n", delta, comp, enc->sample_rate);
521
-//                fprintf(stderr, "drift:%f len:%d opts:%lld ipts:%lld fifo:%d\n", delta, -1, ost->sync_opts, (int64_t)(ost->sync_ipts * enc->sample_rate), fifo_size(&ost->fifo, ost->fifo.rptr)/(ost->st->codec.channels * 2));
521
+//                fprintf(stderr, "drift:%f len:%d opts:%lld ipts:%lld fifo:%d\n", delta, -1, ost->sync_opts, (int64_t)(get_sync_ipts(ost) * enc->sample_rate), fifo_size(&ost->fifo, ost->fifo.rptr)/(ost->st->codec.channels * 2));
522 522
                 av_resample_compensate(*(struct AVResampleContext**)ost->resample, comp, enc->sample_rate);
523 523
             }
524 524
         } 
525 525
     }else
526
-        ost->sync_opts= lrintf(ost->sync_ipts * enc->sample_rate)
526
+        ost->sync_opts= lrintf(get_sync_ipts(ost) * enc->sample_rate)
527 527
                         - fifo_size(&ost->fifo, ost->fifo.rptr)/(ost->st->codec.channels * 2); //FIXME wrong
528 528
 
529 529
     if (ost->audio_resample) {
... ...
@@ -709,7 +721,7 @@ static void do_video_out(AVFormatContext *s,
709 709
 
710 710
     if(video_sync_method){
711 711
         double vdelta;
712
-        vdelta = ost->sync_ipts / av_q2d(enc->time_base) - ost->sync_opts;
712
+        vdelta = get_sync_ipts(ost) / av_q2d(enc->time_base) - ost->sync_opts;
713 713
         //FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c
714 714
         if (vdelta < -1.1)
715 715
             nb_frames = 0;
... ...
@@ -726,7 +738,7 @@ static void do_video_out(AVFormatContext *s,
726 726
                 fprintf(stderr, "*** %d dup!\n", nb_frames-1);
727 727
         }
728 728
     }else
729
-        ost->sync_opts= lrintf(ost->sync_ipts / av_q2d(enc->time_base));
729
+        ost->sync_opts= lrintf(get_sync_ipts(ost) / av_q2d(enc->time_base));
730 730
 
731 731
     nb_frames= FFMIN(nb_frames, max_frames[CODEC_TYPE_VIDEO] - ost->frame_number);
732 732
     if (nb_frames <= 0) 
... ...
@@ -1267,7 +1279,7 @@ static int output_packet(AVInputStream *ist, int ist_index,
1267 1267
                                ((double)ost->st->pts.val * ost->st->time_base.num / ost->st->time_base.den));
1268 1268
 #endif
1269 1269
                         /* set the input output pts pairs */
1270
-                        ost->sync_ipts = (double)(ist->pts + input_files_ts_offset[ist->file_index] - start_time)/ AV_TIME_BASE;
1270
+                        //ost->sync_ipts = (double)(ist->pts + input_files_ts_offset[ist->file_index] - start_time)/ AV_TIME_BASE;
1271 1271
 
1272 1272
                         if (ost->encoding_needed) {
1273 1273
                             switch(ost->st->codec.codec_type) {
... ...
@@ -1460,6 +1472,13 @@ static int av_encode(AVFormatContext **output_files,
1460 1460
             fprintf(stderr,"Could not find input stream #%d.%d\n", fi, si);
1461 1461
             exit(1);
1462 1462
         }
1463
+        fi = stream_maps[i].sync_file_index;
1464
+        si = stream_maps[i].sync_stream_index;
1465
+        if (fi < 0 || fi > nb_input_files - 1 ||
1466
+            si < 0 || si > file_table[fi].nb_streams - 1) {
1467
+            fprintf(stderr,"Could not find sync stream #%d.%d\n", fi, si);
1468
+            exit(1);
1469
+        }
1463 1470
     }
1464 1471
     
1465 1472
     ost_table = av_mallocz(sizeof(AVOutputStream *) * nb_ostreams);
... ...
@@ -1524,6 +1543,9 @@ static int av_encode(AVFormatContext **output_files,
1524 1524
             }
1525 1525
             ist = ist_table[ost->source_index];
1526 1526
             ist->discard = 0;
1527
+            ost->sync_ist = (nb_stream_maps > 0) ?
1528
+                ist_table[file_table[stream_maps[n-1].sync_file_index].ist_index +
1529
+                         stream_maps[n-1].sync_stream_index] : ist;
1527 1530
         }
1528 1531
     }
1529 1532
 
... ...
@@ -1728,11 +1750,16 @@ static int av_encode(AVFormatContext **output_files,
1728 1728
         fprintf(stderr, "Stream mapping:\n");
1729 1729
         for(i=0;i<nb_ostreams;i++) {
1730 1730
             ost = ost_table[i];
1731
-            fprintf(stderr, "  Stream #%d.%d -> #%d.%d\n",
1731
+            fprintf(stderr, "  Stream #%d.%d -> #%d.%d",
1732 1732
                     ist_table[ost->source_index]->file_index,
1733 1733
                     ist_table[ost->source_index]->index,
1734 1734
                     ost->file_index, 
1735 1735
                     ost->index);
1736
+            if (ost->sync_ist != ist_table[ost->source_index])
1737
+                fprintf(stderr, " [sync #%d.%d]",
1738
+                        ost->sync_ist->file_index,
1739
+                        ost->sync_ist->index);
1740
+            fprintf(stderr, "\n");
1736 1741
         }
1737 1742
     }
1738 1743
 
... ...
@@ -2816,6 +2843,16 @@ static void opt_map(const char *arg)
2816 2816
         p++;
2817 2817
 
2818 2818
     m->stream_index = strtol(p, (char **)&p, 0);
2819
+    if (*p) {
2820
+        p++;
2821
+        m->sync_file_index = strtol(p, (char **)&p, 0);
2822
+        if (*p)
2823
+            p++;
2824
+        m->sync_stream_index = strtol(p, (char **)&p, 0);
2825
+    } else {
2826
+        m->sync_file_index = m->file_index;
2827
+        m->sync_stream_index = m->stream_index;
2828
+    }
2819 2829
 }
2820 2830
 
2821 2831
 static void opt_map_meta_data(const char *arg)
... ...
@@ -3929,7 +3966,7 @@ const OptionDef options[] = {
3929 3929
     { "img", HAS_ARG, {(void*)opt_image_format}, "force image format", "img_fmt" },
3930 3930
     { "i", HAS_ARG, {(void*)opt_input_file}, "input file name", "filename" },
3931 3931
     { "y", OPT_BOOL, {(void*)&file_overwrite}, "overwrite output files" },
3932
-    { "map", HAS_ARG | OPT_EXPERT, {(void*)opt_map}, "set input stream mapping", "file:stream" },
3932
+    { "map", HAS_ARG | OPT_EXPERT, {(void*)opt_map}, "set input stream mapping", "file:stream[:syncfile:syncstream]" },
3933 3933
     { "map_meta_data", HAS_ARG | OPT_EXPERT, {(void*)opt_map_meta_data}, "set meta data information of outfile from infile", "outfile:infile" },
3934 3934
     { "t", HAS_ARG, {(void*)opt_recording_time}, "set the recording time", "duration" },
3935 3935
     { "fs", HAS_ARG | OPT_INT, {(void*)&limit_filesize}, "set the limit file size", "limit_size" }, //