Newer
Older
Michael Niedermayer
committed
double scale, scale_sum=0;
char type[3]= {'Y','U','V'};
sprintf(buf + strlen(buf), "PSNR=");
for(j=0; j<3; j++){
if(is_last_report){
error= enc->error[j];
scale= enc->width*enc->height*255.0*255.0*frame_number;
}else{
error= enc->coded_frame->error[j];
scale= enc->width*enc->height*255.0*255.0;
}
if(j) scale/=4;
error_sum += error;
scale_sum += scale;
sprintf(buf + strlen(buf), "%c:%2.2f ", type[j], psnr(error/scale));
}
sprintf(buf + strlen(buf), "*:%2.2f ", psnr(error_sum/scale_sum));
}
Fabrice Bellard
committed
vid = 1;
}
/* compute min output value */
pts = (double)ost->st->pts.val * ost->st->time_base.num / ost->st->time_base.den;
Kareila
committed
if ((pts < ti1) && (pts > 0))
Fabrice Bellard
committed
ti1 = pts;
}
if (ti1 < 0.01)
ti1 = 0.01;
if (verbose || is_last_report) {
bitrate = (double)(total_size * 8) / ti1 / 1000.0;
sprintf(buf + strlen(buf),
Fabrice Bellard
committed
"size=%8.0fkB time=%0.1f bitrate=%6.1fkbits/s",
(double)total_size / 1024, ti1, bitrate);
if (verbose > 1)
sprintf(buf + strlen(buf), " dup=%d drop=%d",
nb_frames_dup, nb_frames_drop);
if (verbose >= 0)
fprintf(stderr, "%s \r", buf);
Fabrice Bellard
committed
fflush(stderr);
}
if (is_last_report && verbose >= 0){
int64_t raw= audio_size + video_size + extra_size;
fprintf(stderr, "\n");
fprintf(stderr, "video:%1.0fkB audio:%1.0fkB global headers:%1.0fkB muxing overhead %f%%\n",
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;
short samples[pkt && pkt->size > AVCODEC_MAX_AUDIO_FRAME_SIZE/2 ? pkt->size : AVCODEC_MAX_AUDIO_FRAME_SIZE/2];
Fabrice Bellard
committed
void *buffer_to_free;
if (pkt && pkt->dts != AV_NOPTS_VALUE) { //FIXME seems redundant, as libavformat does this too
ist->next_pts = ist->pts = pkt->dts;
Fabrice Bellard
committed
} else {
assert(ist->pts == ist->next_pts);
Fabrice Bellard
committed
}
Fabrice Bellard
committed
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
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;
if (ist->decoding_needed) {
switch(ist->st->codec.codec_type) {
case CODEC_TYPE_AUDIO:
/* XXX: could avoid copy if PCM 16 bits with same
endianness as CPU */
ret = avcodec_decode_audio(&ist->st->codec, samples, &data_size,
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;
Wolfram Gloger
committed
ist->next_pts += ((int64_t)AV_TIME_BASE/2 * data_size) /
(ist->st->codec.sample_rate * ist->st->codec.channels);
Fabrice Bellard
committed
break;
case CODEC_TYPE_VIDEO:
data_size = (ist->st->codec.width * ist->st->codec.height * 3) / 2;
/* XXX: allocate picture correctly */
avcodec_get_frame_defaults(&picture);
Fabrice Bellard
committed
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
ret = avcodec_decode_video(&ist->st->codec,
&picture, &got_picture, ptr, len);
ist->st->quality= picture.quality;
if (ret < 0)
goto fail_decode;
if (!got_picture) {
/* no picture yet */
goto discard_packet;
}
if (ist->st->codec.frame_rate_base != 0) {
ist->next_pts += ((int64_t)AV_TIME_BASE *
ist->st->codec.frame_rate_base) /
ist->st->codec.frame_rate;
}
len = 0;
break;
default:
goto fail_decode;
}
} else {
data_buf = ptr;
data_size = len;
ret = len;
len = 0;
}
buffer_to_free = NULL;
if (ist->st->codec.codec_type == CODEC_TYPE_VIDEO) {
pre_process_video_frame(ist, (AVPicture *)&picture,
&buffer_to_free);
}
/* frame rate emulation */
if (ist->st->codec.rate_emu) {
int64_t pts = av_rescale((int64_t) ist->frame * ist->st->codec.frame_rate_base, 1000000, ist->st->codec.frame_rate);
int64_t now = av_gettime() - ist->start;
if (pts > now)
usleep(pts - now);
ist->frame++;
}
#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;
}
}
#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;
ost = ost_table[i];
if (ost->source_index == ist_index) {
os = output_files[ost->file_index];
#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])/ AV_TIME_BASE;
Fabrice Bellard
committed
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
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:
/* find an audio stream for synchro */
{
int i;
AVOutputStream *audio_sync, *ost1;
audio_sync = NULL;
for(i=0;i<nb_ostreams;i++) {
ost1 = ost_table[i];
if (ost1->file_index == ost->file_index &&
ost1->st->codec.codec_type == CODEC_TYPE_AUDIO) {
audio_sync = ost1;
break;
}
}
do_video_out(os, ost, ist, &picture, &frame_size);
video_size += frame_size;
Fabrice Bellard
committed
if (do_vstats && frame_size)
do_video_stats(os, ost, frame_size);
}
break;
default:
av_abort();
}
} else {
AVFrame avframe; //FIXME/XXX remove this
AVPacket opkt;
av_init_packet(&opkt);
Fabrice Bellard
committed
/* no reencoding needed : output the packet directly */
/* force the input stream PTS */
avcodec_get_frame_defaults(&avframe);
Fabrice Bellard
committed
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;
opkt.stream_index= ost->index;
opkt.data= data_buf;
opkt.size= data_size;
opkt.pts= pkt->pts + input_files_ts_offset[ist->file_index];
opkt.dts= pkt->dts + input_files_ts_offset[ist->file_index];
av_interleaved_write_frame(os, &opkt);
Fabrice Bellard
committed
ost->st->codec.frame_number++;
ost->frame_number++;
}
}
}
av_free(buffer_to_free);
}
discard_packet:
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
if (pkt == NULL) {
/* EOF handling */
for(i=0;i<nb_ostreams;i++) {
ost = ost_table[i];
if (ost->source_index == ist_index) {
AVCodecContext *enc= &ost->st->codec;
os = output_files[ost->file_index];
if(ost->st->codec.codec_type == CODEC_TYPE_AUDIO && enc->frame_size <=1)
continue;
if(ost->st->codec.codec_type == CODEC_TYPE_VIDEO && (os->oformat->flags & AVFMT_RAWPICTURE))
continue;
if (ost->encoding_needed) {
for(;;) {
AVPacket pkt;
av_init_packet(&pkt);
pkt.stream_index= ost->index;
switch(ost->st->codec.codec_type) {
case CODEC_TYPE_AUDIO:
ret = avcodec_encode_audio(enc, bit_buffer, VIDEO_BUFFER_SIZE, NULL);
audio_size += ret;
pkt.flags |= PKT_FLAG_KEY;
break;
case CODEC_TYPE_VIDEO:
ret = avcodec_encode_video(enc, bit_buffer, VIDEO_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;
}
if(ret<=0)
break;
pkt.data= bit_buffer;
pkt.size= ret;
if(enc->coded_frame)
pkt.pts= enc->coded_frame->pts;
av_interleaved_write_frame(os, &pkt);
}
}
}
}
}
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;
AVFormatContext *stream_no_data;
int key;
file_table= (AVInputFile*) av_mallocz(nb_input_files * sizeof(AVInputFile));
if (!bit_buffer)
bit_buffer = av_malloc(VIDEO_BUFFER_SIZE);
if (!bit_buffer)
goto fail;
/* 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
if (ist->st->codec.rate_emu) {
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];
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;
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);
}
}
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
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 +
stream_maps[n-1].stream_index;
Brian Foley
committed
/* Sanity check that the stream types match */
if (ist_table[ost->source_index]->st->codec.codec_type != ost->st->codec.codec_type) {
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);
}
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
} 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];
if (ist->discard &&
ist->st->codec.codec_type == ost->st->codec.codec_type) {
ost->source_index = j;
found = 1;
}
}
if (!found) {
/* try again and reuse existing stream */
for(j=0;j<nb_istreams;j++) {
ist = ist_table[j];
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;
}
}
/* for each output stream, we compute the right encoding parameters */
for(i=0;i<nb_ostreams;i++) {
ost = ost_table[i];
ist = ist_table[ost->source_index];
codec = &ost->st->codec;
icodec = &ist->st->codec;
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;
codec->codec_tag = icodec->codec_tag;
codec->bit_rate = icodec->bit_rate;
switch(codec->codec_type) {
case CODEC_TYPE_AUDIO:
codec->sample_rate = icodec->sample_rate;
codec->channels = icodec->channels;
codec->frame_size = icodec->frame_size;
break;
case CODEC_TYPE_VIDEO:
codec->frame_rate = icodec->frame_rate;
Michael Niedermayer
committed
codec->frame_rate_base = icodec->frame_rate_base;
codec->width = icodec->width;
codec->height = icodec->height;
break;
default:
av_abort();
}
} else {
switch(codec->codec_type) {
case CODEC_TYPE_AUDIO:
if (fifo_init(&ost->fifo, 2 * MAX_AUDIO_PACKET_SIZE))
goto fail;
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;
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");
av_abort();
}
}
ist->decoding_needed = 1;
ost->encoding_needed = 1;
break;
case CODEC_TYPE_VIDEO:
codec->height == icodec->height &&
frame_topBand == 0 &&
frame_bottomBand == 0 &&
frame_leftBand == 0 &&
Todd Kirby
committed
frame_rightBand == 0 &&
frame_padtop == 0 &&
frame_padbottom == 0 &&
frame_padleft == 0 &&
frame_padright == 0)
{
ost->video_resample = 0;
ost->video_crop = 0;
Todd Kirby
committed
ost->video_pad = 0;
} else if ((codec->width == icodec->width -
(frame_leftBand + frame_rightBand)) &&
(codec->height == icodec->height -
(frame_topBand + frame_bottomBand)))
{
ost->video_crop = 1;
ost->topBand = frame_topBand;
ost->leftBand = frame_leftBand;
Todd Kirby
committed
} else if ((codec->width == icodec->width +
(frame_padleft + frame_padright)) &&
(codec->height == icodec->height +
(frame_padtop + frame_padbottom))) {
ost->video_resample = 0;
ost->video_crop = 0;
ost->video_pad = 1;
ost->padtop = frame_padtop;
ost->padleft = frame_padleft;
ost->padbottom = frame_padbottom;
ost->padright = frame_padright;
Michael Niedermayer
committed
if( avpicture_alloc( (AVPicture*)&ost->pict_tmp, PIX_FMT_YUV420P,
Todd Kirby
committed
codec->width, codec->height ) )
goto fail;
ost->video_crop = 0; // cropping is handled as part of resample
Michael Niedermayer
committed
if( avpicture_alloc( (AVPicture*)&ost->pict_tmp, PIX_FMT_YUV420P,
codec->width, codec->height ) )
Michael Niedermayer
committed
ost->img_resample_ctx = img_resample_full_init(
Michael Niedermayer
committed
ist->st->codec.width, ist->st->codec.height,
frame_topBand, frame_bottomBand,
Todd Kirby
committed
frame_leftBand, frame_rightBand,
frame_padtop, frame_padbottom,
frame_padleft, frame_padright);
ost->padtop = frame_padtop;
ost->padleft = frame_padleft;
ost->padbottom = frame_padbottom;
ost->padright = frame_padright;
}
ost->encoding_needed = 1;
ist->decoding_needed = 1;
break;
default:
av_abort();
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
/* two pass mode */
if (ost->encoding_needed &&
(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 ?
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;
/* 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\n",
ist_table[ost->source_index]->file_index,
ist_table[ost->source_index]->index,
ost->file_index,
ost->index);
}
}
/* open each encoder */
for(i=0;i<nb_ostreams;i++) {
ost = ost_table[i];
if (ost->encoding_needed) {
AVCodec *codec;
codec = avcodec_find_encoder(ost->st->codec.codec_id);
if (!codec) {
fprintf(stderr, "Unsupported codec for output stream #%d.%d\n",
ost->file_index, ost->index);
exit(1);
}
if (avcodec_open(&ost->st->codec, codec) < 0) {
fprintf(stderr, "Error while opening codec for stream #%d.%d - maybe incorrect parameters such as bit_rate, rate, width or height\n",
ost->file_index, ost->index);
exit(1);
}
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;
codec = avcodec_find_decoder(ist->st->codec.codec_id);
if (!codec) {
fprintf(stderr, "Unsupported codec (id=%d) for input stream #%d.%d\n",
ist->st->codec.codec_id, ist->file_index, ist->index);
exit(1);
}
if (avcodec_open(&ist->st->codec, codec) < 0) {
fprintf(stderr, "Error while opening codec for input stream #%d.%d\n",
ist->file_index, ist->index);
exit(1);
}
//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];
ist->next_pts = 0;
}
/* compute buffer size max (should use a complete heuristic) */
for(i=0;i<nb_input_files;i++) {
file_table[i].buffer_size_max = 2048;
}
/* 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 paramters ?)\n", i);
ret = -EINVAL;
goto fail;
}
#ifndef CONFIG_WIN32
if ( !using_stdin && verbose >= 0) {
fprintf(stderr, "Press [q] to stop encoding\n");
Leon van Stuivenberg
committed
url_set_interrupt_cb(decode_interrupt_cb);
}
#endif
term_init();
stream_no_data = 0;
key = -1;
for(; received_sigterm == 0;) {
double ipts_min= 1e100;
double 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];
if(ost->st->codec.codec_type == CODEC_TYPE_VIDEO)
opts = (double)ost->sync_opts * ost->st->codec.frame_rate_base / ost->st->codec.frame_rate;
else
opts = (double)ost->st->pts.val * ost->st->time_base.num / ost->st->time_base.den;
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;
}
if (file_index < 0) {
Fabrice Bellard
committed
}
if (recording_time > 0 && opts_min >= (recording_time / 1000000.0))
Fabrice Bellard
committed
/* read a frame from it and output it in the fifo */
if (av_read_frame(is, &pkt) < 0) {
if (!pkt.size) {
stream_no_data = is;
} else {
stream_no_data = 0;
}
if (do_pkt_dump) {
av_pkt_dump(stdout, &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;
// fprintf(stderr, "next:%lld dts:%lld off:%lld %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) {
int64_t delta= pkt.dts - ist->next_pts;
if(ABS(delta) > 10LL*AV_TIME_BASE && !copy_ts){
input_files_ts_offset[ist->file_index]-= delta;
if (verbose > 2)
fprintf(stderr, "timestamp discontinuity %lld, new offset= %lld\n", delta, input_files_ts_offset[ist->file_index]);
for(i=0; i<file_table[file_index].nb_streams; i++){
int index= file_table[file_index].ist_index + i;
ist_table[index]->next_pts += delta;
//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) {
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) {
avcodec_close(&ist->st->codec);
}
}
/* finished ! */
ret = 0;
fail1:
if (ist_table) {
for(i=0;i<nb_istreams;i++) {
ist = ist_table[i];
}
if (ost_table) {
for(i=0;i<nb_ostreams;i++) {
ost = ost_table[i];
if (ost) {
if (ost->logfile) {
fclose(ost->logfile);
ost->logfile = NULL;
}
fifo_free(&ost->fifo); /* works even if fifo is not
initialized but set to zero */
if (ost->video_resample)
img_resample_close(ost->img_resample_ctx);
if (ost->audio_resample)
audio_resample_close(ost->resample);
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
}
return ret;
fail:
ret = -ENOMEM;
goto fail1;
}
#if 0
int file_read(const char *filename)
{
URLContext *h;
unsigned char buffer[1024];
int len, i;
if (url_open(&h, filename, O_RDONLY) < 0) {
printf("could not open '%s'\n", filename);
return -1;
}
for(;;) {
len = url_read(h, buffer, sizeof(buffer));
if (len <= 0)
break;
for(i=0;i<len;i++) putchar(buffer[i]);
}
url_close(h);
return 0;
}
#endif
static void opt_image_format(const char *arg)
Fabrice Bellard
committed
{
AVImageFormat *f;
for(f = first_image_format; f != NULL; f = f->next) {
if (!strcmp(arg, f->name))
break;
}
if (!f) {
fprintf(stderr, "Unknown image format: '%s'\n", arg);
exit(1);
}
image_format = f;
}
static void opt_format(const char *arg)
Fabrice Bellard
committed
/* compatibility stuff for pgmyuv */
if (!strcmp(arg, "pgmyuv")) {
opt_image_format(arg);
arg = "image";
}
file_iformat = av_find_input_format(arg);
file_oformat = guess_format(arg, NULL, NULL);
if (!file_iformat && !file_oformat) {
fprintf(stderr, "Unknown input or output format: %s\n", arg);
static void opt_video_bitrate(const char *arg)
static void opt_video_bitrate_tolerance(const char *arg)
{
video_bit_rate_tolerance = atoi(arg) * 1000;
}
static void opt_video_bitrate_max(const char *arg)
{
video_rc_max_rate = atoi(arg) * 1000;
}
static void opt_video_bitrate_min(const char *arg)
{
video_rc_min_rate = atoi(arg) * 1000;
}
static void opt_video_buffer_size(const char *arg)
video_rc_buffer_size = atoi(arg) * 8*1024;
static void opt_video_rc_eq(char *arg)