[FFmpeg-devel] [PATCH 2/4] ffmpeg: use the write_uncoded_frame() API.
Nicolas George
george at nsup.org
Mon Jan 13 10:23:44 CET 2014
Signed-off-by: Nicolas George <george at nsup.org>
---
ffmpeg.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++---------
ffmpeg.h | 1 +
2 files changed, 50 insertions(+), 9 deletions(-)
A few corner cases fixed, and a better magic number for the packet size.
diff --git a/ffmpeg.c b/ffmpeg.c
index 5ccbf10..ae362f6 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -163,6 +163,8 @@ static struct termios oldtty;
static int restore_tty;
#endif
+#define UNCODED_FRAME_PACKET_SIZE (INT_MIN / 3 * 2 + (int)sizeof(AVFrame))
+
static void free_input_threads(void);
@@ -644,7 +646,19 @@ static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
);
}
- ret = av_interleaved_write_frame(s, pkt);
+ if (ost->uncoded_frame) {
+ AVFrame *frame = (AVFrame *)pkt->data;
+ frame->pts = frame->pkt_pts = pkt->pts;
+ frame->pkt_dts = pkt->dts;
+ av_frame_set_pkt_duration(frame, pkt->duration);
+ av_assert0(!ost->encoding_needed);
+ av_assert0(pkt->size == UNCODED_FRAME_PACKET_SIZE);
+ ret = av_write_uncoded_frame(s, pkt->stream_index, frame);
+ pkt->size = 0;
+ pkt->data = NULL;
+ } else {
+ ret = av_interleaved_write_frame(s, pkt);
+ }
if (ret < 0) {
print_error("av_interleaved_write_frame()", ret);
exit_program(1);
@@ -693,6 +707,8 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost,
frame->pts = ost->sync_opts;
ost->sync_opts = frame->pts + frame->nb_samples;
+ if (ost->encoding_needed) {
+ /* TODO reindent */
av_assert0(pkt.size || !pkt.data);
update_benchmark(NULL);
if (avcodec_encode_audio2(enc, &pkt, frame, &got_packet) < 0) {
@@ -700,6 +716,13 @@ static void do_audio_out(AVFormatContext *s, OutputStream *ost,
exit_program(1);
}
update_benchmark("encode_audio %d.%d", ost->file_index, ost->index);
+ } else {
+ av_assert0(ost->uncoded_frame);
+ pkt.pts = pkt.dts = frame->pts;
+ pkt.data = (void *)frame;
+ pkt.size = UNCODED_FRAME_PACKET_SIZE;
+ got_packet = 1;
+ }
if (got_packet) {
if (pkt.pts != AV_NOPTS_VALUE)
@@ -923,7 +946,7 @@ static void do_video_out(AVFormatContext *s,
in_picture->top_field_first = !!ost->top_field_first;
if (in_picture->interlaced_frame) {
- if (enc->codec->id == AV_CODEC_ID_MJPEG)
+ if (enc->codec && enc->codec->id == AV_CODEC_ID_MJPEG)
enc->field_order = in_picture->top_field_first ? AV_FIELD_TT:AV_FIELD_BB;
else
enc->field_order = in_picture->top_field_first ? AV_FIELD_TB:AV_FIELD_BT;
@@ -968,6 +991,8 @@ static void do_video_out(AVFormatContext *s,
av_log(NULL, AV_LOG_DEBUG, "Forced keyframe at time %f\n", pts_time);
}
+ if (ost->encoding_needed) {
+ /* TODO reindent */
update_benchmark(NULL);
ret = avcodec_encode_video2(enc, &pkt, in_picture, &got_packet);
update_benchmark("encode_video %d.%d", ost->file_index, ost->index);
@@ -975,6 +1000,13 @@ static void do_video_out(AVFormatContext *s,
av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n");
exit_program(1);
}
+ } else {
+ av_assert0(ost->uncoded_frame);
+ pkt.pts = pkt.dts = in_picture->pts;
+ pkt.data = (void *)in_picture;
+ pkt.size = UNCODED_FRAME_PACKET_SIZE;
+ got_packet = 1;
+ }
if (got_packet) {
if (pkt.pts == AV_NOPTS_VALUE && !(enc->codec->capabilities & CODEC_CAP_DELAY))
@@ -1117,7 +1149,8 @@ static int reap_filters(void)
break;
case AVMEDIA_TYPE_AUDIO:
filtered_frame->pts = frame_pts;
- if (!(ost->st->codec->codec->capabilities & CODEC_CAP_PARAM_CHANGE) &&
+ if (!(ost->st->codec->codec &&
+ (ost->st->codec->codec->capabilities & CODEC_CAP_PARAM_CHANGE)) &&
ost->st->codec->channels != av_frame_get_channels(filtered_frame)) {
av_log(NULL, AV_LOG_ERROR,
"Audio filter graph output is not normalized and encoder does not support parameter changes\n");
@@ -1978,7 +2011,8 @@ static int output_packet(InputStream *ist, const AVPacket *pkt)
for (i = 0; pkt && i < nb_output_streams; i++) {
OutputStream *ost = output_streams[i];
- if (!check_output_constraints(ist, ost) || ost->encoding_needed)
+ if (!check_output_constraints(ist, ost) || ost->encoding_needed ||
+ ost->uncoded_frame)
continue;
do_streamcopy(ist, ost, pkt);
@@ -2411,6 +2445,9 @@ static int transcode_init(void)
abort();
}
} else {
+ ret = av_write_uncoded_frame_query(oc, ost->index);
+ if (ret < 0) {
+ /* TODO reindent */
if (!ost->enc)
ost->enc = avcodec_find_encoder(codec->codec_id);
if (!ost->enc) {
@@ -2420,10 +2457,15 @@ static int transcode_init(void)
ret = AVERROR(EINVAL);
goto dump_format;
}
+ ost->encoding_needed = 1;
+ } else {
+ av_log(oc, AV_LOG_VERBOSE, "Using uncoded frame output "
+ "for stream #%d\n", ost->index);
+ ost->uncoded_frame = 1;
+ }
if (ist)
ist->decoding_needed++;
- ost->encoding_needed = 1;
if (!ost->filter &&
(codec->codec_type == AVMEDIA_TYPE_VIDEO ||
@@ -3400,10 +3442,8 @@ static int transcode(void)
/* close each encoder */
for (i = 0; i < nb_output_streams; i++) {
ost = output_streams[i];
- if (ost->encoding_needed) {
- av_freep(&ost->st->codec->stats_in);
- avcodec_close(ost->st->codec);
- }
+ av_freep(&ost->st->codec->stats_in);
+ avcodec_close(ost->st->codec);
}
/* close each decoder */
diff --git a/ffmpeg.h b/ffmpeg.h
index 433baf8..55d7235 100644
--- a/ffmpeg.h
+++ b/ffmpeg.h
@@ -350,6 +350,7 @@ typedef struct OutputStream {
int source_index; /* InputStream index */
AVStream *st; /* stream in the output file */
int encoding_needed; /* true if encoding needed for this stream */
+ int uncoded_frame; /* true if using the uncoded frame API */
int frame_number;
/* input pts and corresponding output pts
for A/V sync */
--
1.8.5.2
More information about the ffmpeg-devel
mailing list