Newer
Older
video_size/1024.0,
audio_size/1024.0,
extra_size/1024.0,
100.0*(total_size - raw)/raw
);
}
Fabrice Bellard
committed
/* pkt = NULL means EOF (needed to flush decoder buffers) */
static int output_packet(AVInputStream *ist, int ist_index,
AVOutputStream **ost_table, int nb_ostreams,
Wolfram Gloger
committed
const AVPacket *pkt)
Fabrice Bellard
committed
{
AVFormatContext *os;
AVOutputStream *ost;
uint8_t *ptr;
int len, ret, i;
uint8_t *data_buf;
int data_size, got_picture;
AVFrame picture;
void *buffer_to_free;
static unsigned int samples_size= 0;
static short *samples= NULL;
Fabrice Bellard
committed
AVSubtitle subtitle, *subtitle_to_free;
int got_subtitle;
if(!pkt){
ist->pts= ist->next_pts; // needed for last packet if vsync=0
} else if (pkt->dts != AV_NOPTS_VALUE) { //FIXME seems redundant, as libavformat does this too
ist->next_pts = ist->pts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q);
Fabrice Bellard
committed
} else {
Michael Niedermayer
committed
// assert(ist->pts == ist->next_pts);
Fabrice Bellard
committed
}
Fabrice Bellard
committed
if (pkt == NULL) {
/* EOF handling */
ptr = NULL;
len = 0;
goto handle_eof;
}
len = pkt->size;
ptr = pkt->data;
while (len > 0) {
handle_eof:
/* decode the packet if needed */
data_buf = NULL; /* fail safe */
data_size = 0;
Fabrice Bellard
committed
subtitle_to_free = NULL;
Fabrice Bellard
committed
if (ist->decoding_needed) {
Michael Niedermayer
committed
switch(ist->st->codec->codec_type) {
Baptiste Coudurier
committed
samples= av_fast_realloc(samples, &samples_size, FFMAX(pkt->size*sizeof(*samples), AVCODEC_MAX_AUDIO_FRAME_SIZE));
Fabrice Bellard
committed
/* XXX: could avoid copy if PCM 16 bits with same
endianness as CPU */
ret = avcodec_decode_audio2(ist->st->codec, samples, &data_size,
Fabrice Bellard
committed
ptr, len);
if (ret < 0)
goto fail_decode;
ptr += ret;
len -= ret;
/* Some bug in mpeg audio decoder gives */
/* data_size < 0, it seems they are overflows */
if (data_size <= 0) {
/* no audio frame */
continue;
}
data_buf = (uint8_t *)samples;
ist->next_pts += ((int64_t)AV_TIME_BASE/2 * data_size) /
Michael Niedermayer
committed
(ist->st->codec->sample_rate * ist->st->codec->channels);
Fabrice Bellard
committed
case CODEC_TYPE_VIDEO:
Michael Niedermayer
committed
data_size = (ist->st->codec->width * ist->st->codec->height * 3) / 2;
Fabrice Bellard
committed
/* XXX: allocate picture correctly */
avcodec_get_frame_defaults(&picture);
ret = avcodec_decode_video(ist->st->codec,
Fabrice Bellard
committed
&picture, &got_picture, ptr, len);
ist->st->quality= picture.quality;
Fabrice Bellard
committed
goto fail_decode;
if (!got_picture) {
/* no picture yet */
goto discard_packet;
}
Michael Niedermayer
committed
if (ist->st->codec->time_base.num != 0) {
ist->next_pts += ((int64_t)AV_TIME_BASE *
Michael Niedermayer
committed
ist->st->codec->time_base.num) /
ist->st->codec->time_base.den;
Fabrice Bellard
committed
}
len = 0;
break;
Fabrice Bellard
committed
case CODEC_TYPE_SUBTITLE:
ret = avcodec_decode_subtitle(ist->st->codec,
Fabrice Bellard
committed
&subtitle, &got_subtitle, ptr, len);
if (ret < 0)
Fabrice Bellard
committed
goto fail_decode;
Fabrice Bellard
committed
if (!got_subtitle) {
goto discard_packet;
Fabrice Bellard
committed
}
Fabrice Bellard
committed
subtitle_to_free = &subtitle;
len = 0;
break;
default:
goto fail_decode;
}
} else {
switch(ist->st->codec->codec_type) {
case CODEC_TYPE_AUDIO:
ist->next_pts += ((int64_t)AV_TIME_BASE * ist->st->codec->frame_size) /
(ist->st->codec->sample_rate * ist->st->codec->channels);
break;
case CODEC_TYPE_VIDEO:
if (ist->st->codec->time_base.num != 0) {
ist->next_pts += ((int64_t)AV_TIME_BASE *
ist->st->codec->time_base.num) /
ist->st->codec->time_base.den;
}
break;
Fabrice Bellard
committed
}
data_buf = ptr;
data_size = len;
ret = len;
len = 0;
}
Fabrice Bellard
committed
buffer_to_free = NULL;
if (ist->st->codec->codec_type == CODEC_TYPE_VIDEO) {
pre_process_video_frame(ist, (AVPicture *)&picture,
&buffer_to_free);
}
Fabrice Bellard
committed
// preprocess audio (volume)
if (ist->st->codec->codec_type == CODEC_TYPE_AUDIO) {
if (audio_volume != 256) {
short *volp;
volp = samples;
for(i=0;i<(data_size / sizeof(short));i++) {
int v = ((*volp) * audio_volume + 128) >> 8;
if (v < -32768) v = -32768;
if (v > 32767) v = 32767;
*volp++ = v;
}
/* frame rate emulation */
if (ist->st->codec->rate_emu) {
int64_t pts = av_rescale((int64_t) ist->frame * ist->st->codec->time_base.num, 1000000, ist->st->codec->time_base.den);
int64_t now = av_gettime() - ist->start;
if (pts > now)
usleep(pts - now);
Fabrice Bellard
committed
ist->frame++;
}
Fabrice Bellard
committed
#if 0
/* mpeg PTS deordering : if it is a P or I frame, the PTS
is the one of the next displayed one */
/* XXX: add mpeg4 too ? */
if (ist->st->codec->codec_id == CODEC_ID_MPEG1VIDEO) {
if (ist->st->codec->pict_type != B_TYPE) {
int64_t tmp;
tmp = ist->last_ip_pts;
ist->last_ip_pts = ist->frac_pts.val;
ist->frac_pts.val = tmp;
Fabrice Bellard
committed
}
}
Fabrice Bellard
committed
#endif
/* if output time reached then transcode raw format,
encode packets and output them */
if (start_time == 0 || ist->pts >= start_time)
for(i=0;i<nb_ostreams;i++) {
int frame_size;
Fabrice Bellard
committed
ost = ost_table[i];
if (ost->source_index == ist_index) {
os = output_files[ost->file_index];
Fabrice Bellard
committed
#if 0
printf("%d: got pts=%0.3f %0.3f\n", i,
(double)pkt->pts / AV_TIME_BASE,
((double)ist->pts / AV_TIME_BASE) -
((double)ost->st->pts.val * ost->st->time_base.num / ost->st->time_base.den));
Fabrice Bellard
committed
#endif
/* set the input output pts pairs */
//ost->sync_ipts = (double)(ist->pts + input_files_ts_offset[ist->file_index] - start_time)/ AV_TIME_BASE;
if (ost->encoding_needed) {
switch(ost->st->codec->codec_type) {
case CODEC_TYPE_AUDIO:
do_audio_out(os, ost, ist, data_buf, data_size);
break;
case CODEC_TYPE_VIDEO:
do_video_out(os, ost, ist, &picture, &frame_size);
video_size += frame_size;
if (vstats_filename && frame_size)
do_video_stats(os, ost, frame_size);
break;
case CODEC_TYPE_SUBTITLE:
do_subtitle_out(os, ost, ist, &subtitle,
pkt->pts);
break;
default:
}
} else {
AVFrame avframe; //FIXME/XXX remove this
AVPacket opkt;
av_init_packet(&opkt);
if (!ost->frame_number && !(pkt->flags & PKT_FLAG_KEY))
continue;
/* no reencoding needed : output the packet directly */
/* force the input stream PTS */
avcodec_get_frame_defaults(&avframe);
ost->st->codec->coded_frame= &avframe;
avframe.key_frame = pkt->flags & PKT_FLAG_KEY;
if(ost->st->codec->codec_type == CODEC_TYPE_AUDIO)
audio_size += data_size;
else if (ost->st->codec->codec_type == CODEC_TYPE_VIDEO) {
video_size += data_size;
ost->sync_opts++;
}
opkt.stream_index= ost->index;
if(pkt->pts != AV_NOPTS_VALUE)
Michael Niedermayer
committed
opkt.pts= av_rescale_q(pkt->pts, ist->st->time_base, ost->st->time_base);
else
opkt.pts= AV_NOPTS_VALUE;
if (pkt->dts == AV_NOPTS_VALUE)
opkt.dts = av_rescale_q(ist->next_pts, AV_TIME_BASE_Q, ost->st->time_base);
opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base);
opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->st->time_base);
opkt.flags= pkt->flags;
//FIXME remove the following 2 lines they shall be replaced by the bitstream filters
if(av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, data_buf, data_size, pkt->flags & PKT_FLAG_KEY))
opkt.destruct= av_destruct_packet;
write_frame(os, &opkt, ost->st->codec, bitstream_filters[ost->file_index][pkt->stream_index]);
ost->st->codec->frame_number++;
ost->frame_number++;
av_free_packet(&opkt);
Fabrice Bellard
committed
}
}
}
av_free(buffer_to_free);
/* XXX: allocate the subtitles in the codec ? */
if (subtitle_to_free) {
if (subtitle_to_free->rects != NULL) {
for (i = 0; i < subtitle_to_free->num_rects; i++) {
av_free(subtitle_to_free->rects[i].bitmap);
av_free(subtitle_to_free->rects[i].rgba_palette);
av_freep(&subtitle_to_free->rects);
Fabrice Bellard
committed
}
subtitle_to_free->num_rects = 0;
subtitle_to_free = NULL;
Fabrice Bellard
committed
}
}
Fabrice Bellard
committed
discard_packet:
if (pkt == NULL) {
/* EOF handling */
for(i=0;i<nb_ostreams;i++) {
ost = ost_table[i];
if (ost->source_index == ist_index) {
Michael Niedermayer
committed
AVCodecContext *enc= ost->st->codec;
os = output_files[ost->file_index];
Michael Niedermayer
committed
if(ost->st->codec->codec_type == CODEC_TYPE_AUDIO && enc->frame_size <=1)
Michael Niedermayer
committed
if(ost->st->codec->codec_type == CODEC_TYPE_VIDEO && (os->oformat->flags & AVFMT_RAWPICTURE))
continue;
if (ost->encoding_needed) {
for(;;) {
AVPacket pkt;
int fifo_bytes;
av_init_packet(&pkt);
pkt.stream_index= ost->index;
Michael Niedermayer
committed
switch(ost->st->codec->codec_type) {
fifo_bytes = av_fifo_size(&ost->fifo);
ret = 0;
/* encode any samples remaining in fifo */
if(fifo_bytes > 0 && enc->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME) {
int fs_tmp = enc->frame_size;
enc->frame_size = fifo_bytes / (2 * enc->channels);
if(av_fifo_read(&ost->fifo, (uint8_t *)samples, fifo_bytes) == 0) {
ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, samples);
}
enc->frame_size = fs_tmp;
ret = avcodec_encode_audio(enc, bit_buffer, bit_buffer_size, NULL);
}
audio_size += ret;
pkt.flags |= PKT_FLAG_KEY;
break;
case CODEC_TYPE_VIDEO:
ret = avcodec_encode_video(enc, bit_buffer, bit_buffer_size, NULL);
video_size += ret;
if(enc->coded_frame && enc->coded_frame->key_frame)
pkt.flags |= PKT_FLAG_KEY;
if (ost->logfile && enc->stats_out) {
fprintf(ost->logfile, "%s", enc->stats_out);
}
break;
default:
ret=-1;
}
pkt.data= bit_buffer;
if(enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
Michael Niedermayer
committed
write_frame(os, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
}
}
}
}
}
Fabrice Bellard
committed
return 0;
fail_decode:
return -1;
}
/*
* The following code is the main loop of the file converter
*/
static int av_encode(AVFormatContext **output_files,
int nb_output_files,
AVFormatContext **input_files,
int nb_input_files,
AVStreamMap *stream_maps, int nb_stream_maps)
{
int ret, i, j, k, n, nb_istreams = 0, nb_ostreams = 0;
AVFormatContext *is, *os;
AVCodecContext *codec, *icodec;
AVOutputStream *ost, **ost_table = NULL;
AVInputStream *ist, **ist_table = NULL;
int key;
file_table= (AVInputFile*) av_mallocz(nb_input_files * sizeof(AVInputFile));
/* input stream init */
j = 0;
for(i=0;i<nb_input_files;i++) {
is = input_files[i];
file_table[i].ist_index = j;
file_table[i].nb_streams = is->nb_streams;
j += is->nb_streams;
}
nb_istreams = j;
ist_table = av_mallocz(nb_istreams * sizeof(AVInputStream *));
if (!ist_table)
for(i=0;i<nb_istreams;i++) {
ist = av_mallocz(sizeof(AVInputStream));
if (!ist)
goto fail;
ist_table[i] = ist;
}
j = 0;
for(i=0;i<nb_input_files;i++) {
is = input_files[i];
for(k=0;k<is->nb_streams;k++) {
ist = ist_table[j++];
ist->st = is->streams[k];
ist->file_index = i;
ist->index = k;
ist->discard = 1; /* the stream is discarded by default
(changed later) */
Max Krasnyansky
committed
Michael Niedermayer
committed
if (ist->st->codec->rate_emu) {
Max Krasnyansky
committed
ist->start = av_gettime();
ist->frame = 0;
}
}
}
/* output stream init */
nb_ostreams = 0;
for(i=0;i<nb_output_files;i++) {
os = output_files[i];
if (!os->nb_streams) {
fprintf(stderr, "Output file does not contain any stream\n");
exit(1);
}
nb_ostreams += os->nb_streams;
}
if (nb_stream_maps > 0 && nb_stream_maps != nb_ostreams) {
fprintf(stderr, "Number of stream maps must match number of output streams\n");
exit(1);
}
Brian Foley
committed
/* Sanity check the mapping args -- do the input files & streams exist? */
for(i=0;i<nb_stream_maps;i++) {
int fi = stream_maps[i].file_index;
int si = stream_maps[i].stream_index;
Brian Foley
committed
if (fi < 0 || fi > nb_input_files - 1 ||
si < 0 || si > file_table[fi].nb_streams - 1) {
fprintf(stderr,"Could not find input stream #%d.%d\n", fi, si);
exit(1);
}
fi = stream_maps[i].sync_file_index;
si = stream_maps[i].sync_stream_index;
if (fi < 0 || fi > nb_input_files - 1 ||
si < 0 || si > file_table[fi].nb_streams - 1) {
fprintf(stderr,"Could not find sync stream #%d.%d\n", fi, si);
exit(1);
}
Brian Foley
committed
}
ost_table = av_mallocz(sizeof(AVOutputStream *) * nb_ostreams);
if (!ost_table)
goto fail;
for(i=0;i<nb_ostreams;i++) {
ost = av_mallocz(sizeof(AVOutputStream));
if (!ost)
goto fail;
ost_table[i] = ost;
}
n = 0;
for(k=0;k<nb_output_files;k++) {
os = output_files[k];
for(i=0;i<os->nb_streams;i++) {
int found;
ost = ost_table[n++];
ost->file_index = k;
ost->index = i;
ost->st = os->streams[i];
if (nb_stream_maps > 0) {
ost->source_index = file_table[stream_maps[n-1].file_index].ist_index +
Brian Foley
committed
/* Sanity check that the stream types match */
Michael Niedermayer
committed
if (ist_table[ost->source_index]->st->codec->codec_type != ost->st->codec->codec_type) {
Brian Foley
committed
fprintf(stderr, "Codec type mismatch for mapping #%d.%d -> #%d.%d\n",
stream_maps[n-1].file_index, stream_maps[n-1].stream_index,
ost->file_index, ost->index);
exit(1);
}
} else {
/* get corresponding input stream index : we select the first one with the right type */
found = 0;
for(j=0;j<nb_istreams;j++) {
ist = ist_table[j];
Michael Niedermayer
committed
ist->st->codec->codec_type == ost->st->codec->codec_type) {
Nathan Kurz
committed
break;
if (!found) {
/* try again and reuse existing stream */
for(j=0;j<nb_istreams;j++) {
ist = ist_table[j];
Michael Niedermayer
committed
if (ist->st->codec->codec_type == ost->st->codec->codec_type) {
ost->source_index = j;
found = 1;
}
}
if (!found) {
fprintf(stderr, "Could not find input stream matching output stream #%d.%d\n",
ost->file_index, ost->index);
exit(1);
}
}
}
ist = ist_table[ost->source_index];
ist->discard = 0;
ost->sync_ist = (nb_stream_maps > 0) ?
ist_table[file_table[stream_maps[n-1].sync_file_index].ist_index +
stream_maps[n-1].sync_stream_index] : ist;
}
}
/* for each output stream, we compute the right encoding parameters */
for(i=0;i<nb_ostreams;i++) {
ost = ost_table[i];
Michael Niedermayer
committed
os = output_files[ost->file_index];
Michael Niedermayer
committed
codec = ost->st->codec;
icodec = ist->st->codec;
if (!ost->st->language[0])
av_strlcpy(ost->st->language, ist->st->language,
sizeof(ost->st->language));
if (ost->st->stream_copy) {
/* if stream_copy is selected, no need to decode or encode */
codec->codec_id = icodec->codec_id;
codec->codec_type = icodec->codec_type;
Michael Niedermayer
committed
if(!codec->codec_tag){
if( !os->oformat->codec_tag
|| av_codec_get_id (os->oformat->codec_tag, icodec->codec_tag) > 0
|| av_codec_get_tag(os->oformat->codec_tag, icodec->codec_id) <= 0)
codec->codec_tag = icodec->codec_tag;
}
codec->bit_rate = icodec->bit_rate;
codec->extradata= icodec->extradata;
codec->extradata_size= icodec->extradata_size;
Michael Niedermayer
committed
if(av_q2d(icodec->time_base) > av_q2d(ist->st->time_base) && av_q2d(ist->st->time_base) < 1.0/1000)
codec->time_base = icodec->time_base;
else
codec->time_base = ist->st->time_base;
switch(codec->codec_type) {
case CODEC_TYPE_AUDIO:
codec->sample_rate = icodec->sample_rate;
codec->channels = icodec->channels;
codec->frame_size = icodec->frame_size;
if(codec->block_align == 1 && codec->codec_id == CODEC_ID_MP3)
codec->block_align= 0;
break;
case CODEC_TYPE_VIDEO:
Matthijs Douze
committed
if(using_vhook) {
fprintf(stderr,"-vcodec copy and -vhook are incompatible (frames are not decoded)\n");
exit(1);
}
codec->pix_fmt = icodec->pix_fmt;
codec->width = icodec->width;
codec->height = icodec->height;
codec->has_b_frames = icodec->has_b_frames;
break;
Fabrice Bellard
committed
case CODEC_TYPE_SUBTITLE:
break;
default:
}
} else {
switch(codec->codec_type) {
case CODEC_TYPE_AUDIO:
if (av_fifo_init(&ost->fifo, 2 * MAX_AUDIO_PACKET_SIZE))
if (codec->channels == icodec->channels &&
codec->sample_rate == icodec->sample_rate) {
ost->audio_resample = 0;
} else {
if (codec->channels != icodec->channels &&
(icodec->codec_id == CODEC_ID_AC3 ||
icodec->codec_id == CODEC_ID_DTS)) {
/* Special case for 5:1 AC3 and DTS input */
/* and mono or stereo output */
/* Request specific number of channels */
icodec->channels = codec->channels;
if (codec->sample_rate == icodec->sample_rate)
ost->audio_resample = 0;
else {
ost->audio_resample = 1;
}
} else {
ost->audio_resample = 1;
if(ost->audio_resample){
ost->resample = audio_resample_init(codec->channels, icodec->channels,
codec->sample_rate, icodec->sample_rate);
if(!ost->resample){
printf("Can't resample. Aborting.\n");
}
}
ist->decoding_needed = 1;
ost->encoding_needed = 1;
break;
case CODEC_TYPE_VIDEO:
ost->video_crop = ((frame_leftBand + frame_rightBand + frame_topBand + frame_bottomBand) != 0);
ost->video_pad = ((frame_padleft + frame_padright + frame_padtop + frame_padbottom) != 0);
ost->video_resample = ((codec->width != icodec->width -
(frame_leftBand + frame_rightBand) +
(frame_padleft + frame_padright)) ||
(codec->height != icodec->height -
(frame_topBand + frame_bottomBand) +
(frame_padtop + frame_padbottom)) ||
(codec->pix_fmt != icodec->pix_fmt));
if (ost->video_crop) {
ost->topBand = frame_topBand;
ost->leftBand = frame_leftBand;
}
if (ost->video_pad) {
Todd Kirby
committed
ost->padtop = frame_padtop;
ost->padleft = frame_padleft;
ost->padbottom = frame_padbottom;
ost->padright = frame_padright;
if (!ost->video_resample) {
avcodec_get_frame_defaults(&ost->pict_tmp);
if( avpicture_alloc( (AVPicture*)&ost->pict_tmp, codec->pix_fmt,
codec->width, codec->height ) )
goto fail;
}
}
if (ost->video_resample) {
if( avpicture_alloc( (AVPicture*)&ost->pict_tmp, codec->pix_fmt,
codec->width, codec->height ) ) {
fprintf(stderr, "Cannot allocate temp picture, check pix fmt\n");
exit(1);
sws_flags = av_get_int(sws_opts, "sws_flags", NULL);
ost->img_resample_ctx = sws_getContext(
icodec->width - (frame_leftBand + frame_rightBand),
icodec->height - (frame_topBand + frame_bottomBand),
icodec->pix_fmt,
codec->width - (frame_padleft + frame_padright),
codec->height - (frame_padtop + frame_padbottom),
codec->pix_fmt,
sws_flags, NULL, NULL, NULL);
if (ost->img_resample_ctx == NULL) {
fprintf(stderr, "Cannot get resampling context\n");
exit(1);
}
ost->resample_height = icodec->height - (frame_topBand + frame_bottomBand);
}
ost->encoding_needed = 1;
ist->decoding_needed = 1;
break;
Fabrice Bellard
committed
case CODEC_TYPE_SUBTITLE:
ost->encoding_needed = 1;
ist->decoding_needed = 1;
break;
default:
Fabrice Bellard
committed
break;
/* two pass mode */
(codec->flags & (CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2))) {
char logfilename[1024];
FILE *f;
int size;
char *logbuffer;
snprintf(logfilename, sizeof(logfilename), "%s-%d.log",
pass_logfilename ?
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
pass_logfilename : DEFAULT_PASS_LOGFILENAME, i);
if (codec->flags & CODEC_FLAG_PASS1) {
f = fopen(logfilename, "w");
if (!f) {
perror(logfilename);
exit(1);
}
ost->logfile = f;
} else {
/* read the log file */
f = fopen(logfilename, "r");
if (!f) {
perror(logfilename);
exit(1);
}
fseek(f, 0, SEEK_END);
size = ftell(f);
fseek(f, 0, SEEK_SET);
logbuffer = av_malloc(size + 1);
if (!logbuffer) {
fprintf(stderr, "Could not allocate log buffer\n");
exit(1);
}
Gael Chardon
committed
size = fread(logbuffer, 1, size, f);
fclose(f);
logbuffer[size] = '\0';
codec->stats_in = logbuffer;
if(codec->codec_type == CODEC_TYPE_VIDEO){
int size= codec->width * codec->height;
bit_buffer_size= FFMAX(bit_buffer_size, 4*size);
}
if (!bit_buffer)
bit_buffer = av_malloc(bit_buffer_size);
if (!bit_buffer)
goto fail;
/* dump the file output parameters - cannot be done before in case
of stream copy */
for(i=0;i<nb_output_files;i++) {
dump_format(output_files[i], i, output_files[i]->filename, 1);
}
/* dump the stream mapping */
if (verbose >= 0) {
fprintf(stderr, "Stream mapping:\n");
for(i=0;i<nb_ostreams;i++) {
ost = ost_table[i];
fprintf(stderr, " Stream #%d.%d -> #%d.%d",
ist_table[ost->source_index]->file_index,
ist_table[ost->source_index]->index,
if (ost->sync_ist != ist_table[ost->source_index])
fprintf(stderr, " [sync #%d.%d]",
ost->sync_ist->file_index,
ost->sync_ist->index);
fprintf(stderr, "\n");
}
/* open each encoder */
for(i=0;i<nb_ostreams;i++) {
ost = ost_table[i];
if (ost->encoding_needed) {
AVCodec *codec;
Michael Niedermayer
committed
codec = avcodec_find_encoder(ost->st->codec->codec_id);
fprintf(stderr, "Unsupported codec for output stream #%d.%d\n",
Michael Niedermayer
committed
if (avcodec_open(ost->st->codec, codec) < 0) {
fprintf(stderr, "Error while opening codec for output stream #%d.%d - maybe incorrect parameters such as bit_rate, rate, width or height\n",
Michael Niedermayer
committed
extra_size += ost->st->codec->extradata_size;
}
}
/* open each decoder */
for(i=0;i<nb_istreams;i++) {
ist = ist_table[i];
if (ist->decoding_needed) {
AVCodec *codec;
Michael Niedermayer
committed
codec = avcodec_find_decoder(ist->st->codec->codec_id);
fprintf(stderr, "Unsupported codec (id=%d) for input stream #%d.%d\n",
Michael Niedermayer
committed
ist->st->codec->codec_id, ist->file_index, ist->index);
Michael Niedermayer
committed
if (avcodec_open(ist->st->codec, codec) < 0) {
fprintf(stderr, "Error while opening codec for input stream #%d.%d\n",
Michael Niedermayer
committed
//if (ist->st->codec->codec_type == CODEC_TYPE_VIDEO)
// ist->st->codec->flags |= CODEC_FLAG_REPEAT_FIELD;
}
}
/* init pts */
for(i=0;i<nb_istreams;i++) {
ist = ist_table[i];
is = input_files[ist->file_index];
Michael Niedermayer
committed
ist->next_pts=0;
if( input_files_ts_offset[ist->file_index] != -is->start_time
&& !(is->start_time == AV_NOPTS_VALUE && input_files_ts_offset[ist->file_index]==0))
Patrice Bensoussan
committed
/* set meta data information from input file if required */
for (i=0;i<nb_meta_data_maps;i++) {
AVFormatContext *out_file;
AVFormatContext *in_file;
int out_file_index = meta_data_maps[i].out_file;
int in_file_index = meta_data_maps[i].in_file;
if ( out_file_index < 0 || out_file_index >= nb_output_files ) {
fprintf(stderr, "Invalid output file index %d map_meta_data(%d,%d)\n", out_file_index, out_file_index, in_file_index);
ret = AVERROR(EINVAL);
Patrice Bensoussan
committed
goto fail;
}
if ( in_file_index < 0 || in_file_index >= nb_input_files ) {
fprintf(stderr, "Invalid input file index %d map_meta_data(%d,%d)\n", in_file_index, out_file_index, in_file_index);
ret = AVERROR(EINVAL);
Patrice Bensoussan
committed
goto fail;
Patrice Bensoussan
committed
out_file = output_files[out_file_index];
in_file = input_files[in_file_index];
strcpy(out_file->title, in_file->title);
strcpy(out_file->author, in_file->author);
strcpy(out_file->copyright, in_file->copyright);
strcpy(out_file->comment, in_file->comment);
strcpy(out_file->album, in_file->album);
out_file->year = in_file->year;
out_file->track = in_file->track;
strcpy(out_file->genre, in_file->genre);
}
/* open files and write file headers */
for(i=0;i<nb_output_files;i++) {
os = output_files[i];
if (av_write_header(os) < 0) {
fprintf(stderr, "Could not write header for output file #%d (incorrect codec parameters ?)\n", i);
ret = AVERROR(EINVAL);
goto fail;
}
if ( !using_stdin && verbose >= 0) {
fprintf(stderr, "Press [q] to stop encoding\n");
Leon van Stuivenberg
committed
url_set_interrupt_cb(decode_interrupt_cb);
}
term_init();
key = -1;
timer_start = av_gettime();
for(; received_sigterm == 0;) {
Patrice Bensoussan
committed
double ipts_min;
double opts_min;
Patrice Bensoussan
committed
ipts_min= 1e100;
opts_min= 1e100;
/* if 'q' pressed, exits */
if (!using_stdin) {
Leon van Stuivenberg
committed
if (q_pressed)
break;
/* read_key() returns 0 on EOF */
key = read_key();
if (key == 'q')
break;
}
Fabrice Bellard
committed
/* select the stream that we must read now by looking at the
smallest output pts */
Fabrice Bellard
committed
for(i=0;i<nb_ostreams;i++) {
Fabrice Bellard
committed
ost = ost_table[i];
os = output_files[ost->file_index];
ist = ist_table[ost->source_index];
Michael Niedermayer
committed
if(ost->st->codec->codec_type == CODEC_TYPE_VIDEO)
opts = ost->sync_opts * av_q2d(ost->st->codec->time_base);
opts = ost->st->pts.val * av_q2d(ost->st->time_base);
ipts = (double)ist->pts;
if (!file_table[ist->file_index].eof_reached){
if(ipts < ipts_min) {
ipts_min = ipts;
if(input_sync ) file_index = ist->file_index;
}
if(opts < opts_min) {
opts_min = opts;
if(!input_sync) file_index = ist->file_index;
}
Michael Niedermayer
committed
if(ost->frame_number >= max_frames[ost->st->codec->codec_type]){
file_index= -1;
break;
}
if (file_index < 0) {
Fabrice Bellard
committed
}
if (recording_time > 0 && opts_min >= (recording_time / 1000000.0))
Fabrice Bellard
committed
/* finish if limit size exhausted */
if (limit_filesize != 0 && limit_filesize < url_ftell(&output_files[0]->pb))
/* read a frame from it and output it in the fifo */
if (av_read_frame(is, &pkt) < 0) {
if (opt_shortest)
break;
else
continue;
if (do_pkt_dump) {
Panagiotis Issaris
committed
av_pkt_dump_log(NULL, AV_LOG_DEBUG, &pkt, do_hex_dump);
Fabrice Bellard
committed
}
/* the following test is needed in case new streams appear
dynamically in stream : we ignore them */
if (pkt.stream_index >= file_table[file_index].nb_streams)
ist_index = file_table[file_index].ist_index + pkt.stream_index;
ist = ist_table[ist_index];
if (ist->discard)
goto discard_packet;
Michael Niedermayer
committed
if (pkt.dts != AV_NOPTS_VALUE)
pkt.dts += av_rescale_q(input_files_ts_offset[ist->file_index], AV_TIME_BASE_Q, ist->st->time_base);
if (pkt.pts != AV_NOPTS_VALUE)
pkt.pts += av_rescale_q(input_files_ts_offset[ist->file_index], AV_TIME_BASE_Q, ist->st->time_base);
// fprintf(stderr, "next:%"PRId64" dts:%"PRId64" off:%"PRId64" %d\n", ist->next_pts, pkt.dts, input_files_ts_offset[ist->file_index], ist->st->codec->codec_type);
if (pkt.dts != AV_NOPTS_VALUE && ist->next_pts != AV_NOPTS_VALUE) {
Michael Niedermayer
committed
int64_t pkt_dts= av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q);
int64_t delta= pkt_dts - ist->next_pts;
if((FFABS(delta) > 1LL*dts_delta_threshold*AV_TIME_BASE || pkt_dts+1<ist->pts)&& !copy_ts){
input_files_ts_offset[ist->file_index]-= delta;
if (verbose > 2)
fprintf(stderr, "timestamp discontinuity %"PRId64", new offset= %"PRId64"\n", delta, input_files_ts_offset[ist->file_index]);
Michael Niedermayer
committed
pkt.dts-= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base);
if(pkt.pts != AV_NOPTS_VALUE)
pkt.pts-= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base);
//fprintf(stderr,"read #%d.%d size=%d\n", ist->file_index, ist->index, pkt.size);
Fabrice Bellard
committed
if (output_packet(ist, ist_index, ost_table, nb_ostreams, &pkt) < 0) {
if (verbose >= 0)
fprintf(stderr, "Error while decoding stream #%d.%d\n",
ist->file_index, ist->index);
Fabrice Bellard
committed
av_free_packet(&pkt);
goto redo;
Fabrice Bellard
committed
Fabrice Bellard
committed
/* dump report by using the output first video and audio streams */
print_report(output_files, ost_table, nb_ostreams, 0);
Fabrice Bellard
committed
/* at the end of stream, we must flush the decoder buffers */
for(i=0;i<nb_istreams;i++) {
ist = ist_table[i];
if (ist->decoding_needed) {
output_packet(ist, i, ost_table, nb_ostreams, NULL);
}
}
term_exit();
Michael Niedermayer
committed
/* write the trailer if needed and close file */
for(i=0;i<nb_output_files;i++) {
os = output_files[i];
av_write_trailer(os);
}
/* dump report by using the first video and audio streams */
print_report(output_files, ost_table, nb_ostreams, 1);
/* close each encoder */
for(i=0;i<nb_ostreams;i++) {
ost = ost_table[i];
if (ost->encoding_needed) {
Michael Niedermayer
committed
av_freep(&ost->st->codec->stats_in);
avcodec_close(ost->st->codec);
/* close each decoder */
for(i=0;i<nb_istreams;i++) {
ist = ist_table[i];
if (ist->decoding_needed) {
Michael Niedermayer
committed
avcodec_close(ist->st->codec);