Originally committed as revision 4308 to svn://svn.ffmpeg.org/ffmpeg/trunk
Wolfram Gloger authored on 2005/05/26 17:59:05... | ... |
@@ -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" }, // |