|
|
|
@ -791,6 +791,197 @@ static void print_report(AVFormatContext **output_files, |
|
|
|
|
fprintf(stderr, "\n"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* pkt = NULL means EOF (needed to flush decoder buffers) */ |
|
|
|
|
static int output_packet(AVInputStream *ist, int ist_index, |
|
|
|
|
AVOutputStream **ost_table, int nb_ostreams, |
|
|
|
|
AVPacket *pkt) |
|
|
|
|
{ |
|
|
|
|
AVFormatContext *os; |
|
|
|
|
AVOutputStream *ost; |
|
|
|
|
uint8_t *ptr; |
|
|
|
|
int len, ret, i; |
|
|
|
|
uint8_t *data_buf; |
|
|
|
|
int data_size, got_picture; |
|
|
|
|
AVFrame picture; |
|
|
|
|
short samples[AVCODEC_MAX_AUDIO_FRAME_SIZE / 2]; |
|
|
|
|
void *buffer_to_free; |
|
|
|
|
|
|
|
|
|
if (pkt && pkt->pts != AV_NOPTS_VALUE) { |
|
|
|
|
ist->pts = pkt->pts; |
|
|
|
|
} else { |
|
|
|
|
ist->pts = ist->next_pts; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
ist->next_pts += ((int64_t)AV_TIME_BASE * data_size) /
|
|
|
|
|
(2 * ist->st->codec.channels); |
|
|
|
|
break; |
|
|
|
|
case CODEC_TYPE_VIDEO: |
|
|
|
|
data_size = (ist->st->codec.width * ist->st->codec.height * 3) / 2; |
|
|
|
|
/* XXX: allocate picture correctly */ |
|
|
|
|
memset(&picture, 0, sizeof(picture)); |
|
|
|
|
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 * os->pts_num / os->pts_den)); |
|
|
|
|
#endif |
|
|
|
|
/* set the input output pts pairs */ |
|
|
|
|
ost->sync_ipts = (double)ist->pts / AV_TIME_BASE; |
|
|
|
|
/* XXX: take into account the various fifos,
|
|
|
|
|
in particular for audio */ |
|
|
|
|
ost->sync_opts = ost->st->pts.val; |
|
|
|
|
//printf("ipts=%lld sync_ipts=%f sync_opts=%lld pts.val=%lld pkt->pts=%lld\n", ist->pts, ost->sync_ipts, ost->sync_opts, ost->st->pts.val, pkt->pts);
|
|
|
|
|
|
|
|
|
|
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, audio_sync); |
|
|
|
|
if (do_vstats && frame_size) |
|
|
|
|
do_video_stats(os, ost, frame_size); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
av_abort(); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
AVFrame avframe; |
|
|
|
|
|
|
|
|
|
/* no reencoding needed : output the packet directly */ |
|
|
|
|
/* force the input stream PTS */ |
|
|
|
|
|
|
|
|
|
memset(&avframe, 0, sizeof(AVFrame)); |
|
|
|
|
ost->st->codec.coded_frame= &avframe; |
|
|
|
|
avframe.key_frame = pkt->flags & PKT_FLAG_KEY;
|
|
|
|
|
|
|
|
|
|
av_write_frame(os, ost->index, data_buf, data_size); |
|
|
|
|
ost->st->codec.frame_number++; |
|
|
|
|
ost->frame_number++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
av_free(buffer_to_free); |
|
|
|
|
} |
|
|
|
|
discard_packet: |
|
|
|
|
return 0; |
|
|
|
|
fail_decode: |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The following code is the main loop of the file converter |
|
|
|
|
*/ |
|
|
|
@ -1191,13 +1382,6 @@ static int av_encode(AVFormatContext **output_files, |
|
|
|
|
for(; received_sigterm == 0;) { |
|
|
|
|
int file_index, ist_index; |
|
|
|
|
AVPacket pkt; |
|
|
|
|
uint8_t *ptr; |
|
|
|
|
int len; |
|
|
|
|
uint8_t *data_buf; |
|
|
|
|
int data_size, got_picture; |
|
|
|
|
AVFrame picture; |
|
|
|
|
short samples[AVCODEC_MAX_AUDIO_FRAME_SIZE / 2]; |
|
|
|
|
void *buffer_to_free; |
|
|
|
|
double pts_min; |
|
|
|
|
|
|
|
|
|
redo: |
|
|
|
@ -1258,179 +1442,28 @@ static int av_encode(AVFormatContext **output_files, |
|
|
|
|
goto discard_packet; |
|
|
|
|
|
|
|
|
|
//fprintf(stderr,"read #%d.%d size=%d\n", ist->file_index, ist->index, pkt.size);
|
|
|
|
|
|
|
|
|
|
if (pkt.pts != AV_NOPTS_VALUE) { |
|
|
|
|
ist->pts = pkt.pts; |
|
|
|
|
} else { |
|
|
|
|
ist->pts = ist->next_pts; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
len = pkt.size; |
|
|
|
|
ptr = pkt.data; |
|
|
|
|
while (len > 0) { |
|
|
|
|
/* 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; |
|
|
|
|
ist->next_pts += ((int64_t)AV_TIME_BASE * data_size) /
|
|
|
|
|
(2 * ist->st->codec.channels); |
|
|
|
|
break; |
|
|
|
|
case CODEC_TYPE_VIDEO: |
|
|
|
|
data_size = (ist->st->codec.width * ist->st->codec.height * 3) / 2; |
|
|
|
|
/* XXX: allocate picture correctly */ |
|
|
|
|
memset(&picture, 0, sizeof(picture)); |
|
|
|
|
ret = avcodec_decode_video(&ist->st->codec,
|
|
|
|
|
&picture, &got_picture, ptr, len); |
|
|
|
|
ist->st->quality= picture.quality; |
|
|
|
|
if (ret < 0) { |
|
|
|
|
fail_decode: |
|
|
|
|
if (output_packet(ist, ist_index, ost_table, nb_ostreams, &pkt) < 0) { |
|
|
|
|
fprintf(stderr, "Error while decoding stream #%d.%d\n", |
|
|
|
|
ist->file_index, ist->index); |
|
|
|
|
av_free_packet(&pkt); |
|
|
|
|
goto redo; |
|
|
|
|
} |
|
|
|
|
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 * os->pts_num / os->pts_den)); |
|
|
|
|
#endif |
|
|
|
|
/* set the input output pts pairs */ |
|
|
|
|
ost->sync_ipts = (double)ist->pts / AV_TIME_BASE; |
|
|
|
|
/* XXX: take into account the various fifos,
|
|
|
|
|
in particular for audio */ |
|
|
|
|
ost->sync_opts = ost->st->pts.val; |
|
|
|
|
//printf("ipts=%lld sync_ipts=%f sync_opts=%lld pts.val=%lld pkt.pts=%lld\n", ist->pts, ost->sync_ipts, ost->sync_opts, ost->st->pts.val, pkt.pts);
|
|
|
|
|
|
|
|
|
|
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, audio_sync); |
|
|
|
|
if (do_vstats && frame_size) |
|
|
|
|
do_video_stats(os, ost, frame_size); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
av_abort(); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
AVFrame avframe; |
|
|
|
|
|
|
|
|
|
/* no reencoding needed : output the packet directly */ |
|
|
|
|
/* force the input stream PTS */ |
|
|
|
|
|
|
|
|
|
memset(&avframe, 0, sizeof(AVFrame)); |
|
|
|
|
ost->st->codec.coded_frame= &avframe; |
|
|
|
|
avframe.key_frame = pkt.flags & PKT_FLAG_KEY;
|
|
|
|
|
|
|
|
|
|
av_write_frame(os, ost->index, data_buf, data_size); |
|
|
|
|
ost->st->codec.frame_number++; |
|
|
|
|
ost->frame_number++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
av_free(buffer_to_free); |
|
|
|
|
} |
|
|
|
|
discard_packet: |
|
|
|
|
av_free_packet(&pkt); |
|
|
|
|
|
|
|
|
|
/* dump report by using the output first video and audio streams */ |
|
|
|
|
print_report(output_files, ost_table, nb_ostreams, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* 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(); |
|
|
|
|
|
|
|
|
|
/* dump report by using the first video and audio streams */ |
|
|
|
|