mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-08 13:22:53 +02:00
avconv: split off streamcopy handling into a separate loop.
This is easier to understand and is less likely to break horribly when a stream is to be both decoded and copied.
This commit is contained in:
parent
a8fe9a7242
commit
7204ec1a88
162
avconv.c
162
avconv.c
@ -1528,6 +1528,83 @@ static void flush_encoders(OutputStream *ost_table, int nb_ostreams)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether a packet from ist should be written into ost at this time
|
||||
*/
|
||||
static int check_output_constraints(InputStream *ist, OutputStream *ost)
|
||||
{
|
||||
OutputFile *of = &output_files[ost->file_index];
|
||||
int ist_index = ist - input_streams;
|
||||
|
||||
if (ost->source_index != ist_index)
|
||||
return 0;
|
||||
|
||||
if (of->start_time && ist->pts < of->start_time)
|
||||
return 0;
|
||||
|
||||
if (of->recording_time != INT64_MAX &&
|
||||
av_compare_ts(ist->pts, AV_TIME_BASE_Q, of->recording_time + of->start_time,
|
||||
(AVRational){1, 1000000}) >= 0) {
|
||||
ost->is_past_recording_time = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *pkt)
|
||||
{
|
||||
OutputFile *of = &output_files[ost->file_index];
|
||||
int64_t ost_tb_start_time = av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base);
|
||||
AVPacket opkt;
|
||||
|
||||
av_init_packet(&opkt);
|
||||
|
||||
if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) &&
|
||||
!ost->copy_initial_nonkeyframes)
|
||||
return;
|
||||
|
||||
/* force the input stream PTS */
|
||||
if (ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
|
||||
audio_size += pkt->size;
|
||||
else if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
video_size += pkt->size;
|
||||
ost->sync_opts++;
|
||||
}
|
||||
|
||||
opkt.stream_index = ost->index;
|
||||
if (pkt->pts != AV_NOPTS_VALUE)
|
||||
opkt.pts = av_rescale_q(pkt->pts, ist->st->time_base, ost->st->time_base) - ost_tb_start_time;
|
||||
else
|
||||
opkt.pts = AV_NOPTS_VALUE;
|
||||
|
||||
if (pkt->dts == AV_NOPTS_VALUE)
|
||||
opkt.dts = av_rescale_q(ist->pts, AV_TIME_BASE_Q, ost->st->time_base);
|
||||
else
|
||||
opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base);
|
||||
opkt.dts -= ost_tb_start_time;
|
||||
|
||||
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( ost->st->codec->codec_id != CODEC_ID_H264
|
||||
&& ost->st->codec->codec_id != CODEC_ID_MPEG1VIDEO
|
||||
&& ost->st->codec->codec_id != CODEC_ID_MPEG2VIDEO
|
||||
) {
|
||||
if (av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, pkt->data, pkt->size, pkt->flags & AV_PKT_FLAG_KEY))
|
||||
opkt.destruct = av_destruct_packet;
|
||||
} else {
|
||||
opkt.data = pkt->data;
|
||||
opkt.size = pkt->size;
|
||||
}
|
||||
|
||||
write_frame(of->ctx, &opkt, ost->st->codec, ost->bitstream_filters);
|
||||
ost->st->codec->frame_number++;
|
||||
ost->frame_number++;
|
||||
av_free_packet(&opkt);
|
||||
}
|
||||
|
||||
/* pkt = NULL means EOF (needed to flush decoder buffers) */
|
||||
static int output_packet(InputStream *ist, int ist_index,
|
||||
OutputStream *ost_table, int nb_ostreams,
|
||||
@ -1569,8 +1646,8 @@ static int output_packet(InputStream *ist, int ist_index,
|
||||
|
||||
//while we have more to decode or while the decoder did output something on EOF
|
||||
while (avpkt.size > 0 || (!pkt && got_output)) {
|
||||
uint8_t *data_buf, *decoded_data_buf;
|
||||
int data_size, decoded_data_size;
|
||||
uint8_t *decoded_data_buf;
|
||||
int decoded_data_size;
|
||||
AVFrame *decoded_frame, *filtered_frame;
|
||||
handle_eof:
|
||||
ist->pts= ist->next_pts;
|
||||
@ -1584,8 +1661,6 @@ static int output_packet(InputStream *ist, int ist_index,
|
||||
decoded_frame = filtered_frame = NULL;
|
||||
decoded_data_buf = NULL; /* fail safe */
|
||||
decoded_data_size= 0;
|
||||
data_buf = avpkt.data;
|
||||
data_size = avpkt.size;
|
||||
subtitle_to_free = NULL;
|
||||
if (ist->decoding_needed) {
|
||||
switch(ist->st->codec->codec_type) {
|
||||
@ -1604,7 +1679,6 @@ static int output_packet(InputStream *ist, int ist_index,
|
||||
return ret;
|
||||
avpkt.data += ret;
|
||||
avpkt.size -= ret;
|
||||
data_size = ret;
|
||||
got_output = decoded_data_size > 0;
|
||||
/* Some bug in mpeg audio decoder gives */
|
||||
/* decoded_data_size < 0, it seems they are overflows */
|
||||
@ -1745,23 +1819,13 @@ static int output_packet(InputStream *ist, int ist_index,
|
||||
/* if output time reached then transcode raw format,
|
||||
encode packets and output them */
|
||||
for (i = 0; i < nb_ostreams; i++) {
|
||||
OutputFile *of = &output_files[ost_table[i].file_index];
|
||||
int frame_size;
|
||||
|
||||
ost = &ost_table[i];
|
||||
if (ost->source_index != ist_index)
|
||||
continue;
|
||||
|
||||
if (of->start_time && ist->pts < of->start_time)
|
||||
if (!check_output_constraints(ist, ost) || !ost->encoding_needed)
|
||||
continue;
|
||||
|
||||
if (of->recording_time != INT64_MAX &&
|
||||
av_compare_ts(ist->pts, AV_TIME_BASE_Q, of->recording_time + of->start_time,
|
||||
(AVRational){1, 1000000}) >= 0) {
|
||||
ost->is_past_recording_time = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
#if CONFIG_AVFILTER
|
||||
if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
|
||||
ost->input_video_filter) {
|
||||
@ -1815,64 +1879,8 @@ static int output_packet(InputStream *ist, int ist_index,
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
} else {
|
||||
AVPacket opkt;
|
||||
int64_t ost_tb_start_time= av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base);
|
||||
|
||||
av_init_packet(&opkt);
|
||||
|
||||
if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) &&
|
||||
!ost->copy_initial_nonkeyframes)
|
||||
#if !CONFIG_AVFILTER
|
||||
continue;
|
||||
#else
|
||||
goto cont;
|
||||
#endif
|
||||
|
||||
/* no reencoding needed : output the packet directly */
|
||||
/* force the input stream PTS */
|
||||
|
||||
if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
|
||||
audio_size += data_size;
|
||||
else if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
video_size += data_size;
|
||||
ost->sync_opts++;
|
||||
}
|
||||
|
||||
opkt.stream_index= ost->index;
|
||||
if(pkt->pts != AV_NOPTS_VALUE)
|
||||
opkt.pts= av_rescale_q(pkt->pts, ist->st->time_base, ost->st->time_base) - ost_tb_start_time;
|
||||
else
|
||||
opkt.pts= AV_NOPTS_VALUE;
|
||||
|
||||
if (pkt->dts == AV_NOPTS_VALUE)
|
||||
opkt.dts = av_rescale_q(ist->pts, AV_TIME_BASE_Q, ost->st->time_base);
|
||||
else
|
||||
opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base);
|
||||
opkt.dts -= ost_tb_start_time;
|
||||
|
||||
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( ost->st->codec->codec_id != CODEC_ID_H264
|
||||
&& ost->st->codec->codec_id != CODEC_ID_MPEG1VIDEO
|
||||
&& ost->st->codec->codec_id != CODEC_ID_MPEG2VIDEO
|
||||
) {
|
||||
if(av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, data_buf, data_size, pkt->flags & AV_PKT_FLAG_KEY))
|
||||
opkt.destruct= av_destruct_packet;
|
||||
} else {
|
||||
opkt.data = data_buf;
|
||||
opkt.size = data_size;
|
||||
}
|
||||
|
||||
write_frame(os, &opkt, ost->st->codec, ost->bitstream_filters);
|
||||
ost->st->codec->frame_number++;
|
||||
ost->frame_number++;
|
||||
av_free_packet(&opkt);
|
||||
}
|
||||
#if CONFIG_AVFILTER
|
||||
cont:
|
||||
frame_available = (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) &&
|
||||
ost->output_video_filter && avfilter_poll_frame(ost->output_video_filter->inputs[0]);
|
||||
if (ost->picref)
|
||||
@ -1895,6 +1903,16 @@ fail:
|
||||
}
|
||||
discard_packet:
|
||||
|
||||
/* handle stream copy */
|
||||
for (i = 0; pkt && i < nb_ostreams; i++) {
|
||||
ost = &ost_table[i];
|
||||
|
||||
if (!check_output_constraints(ist, ost) || ost->encoding_needed)
|
||||
continue;
|
||||
|
||||
do_streamcopy(ist, ost, pkt);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user