FFmpeg
4.4.6
transcoding.c
/*
* Copyright (c) 2010 Nicolas George
* Copyright (c) 2011 Stefano Sabatini
* Copyright (c) 2014 Andrey Utkin
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* @file
* API example for demuxing, decoding, filtering, encoding and muxing
* @example transcoding.c
*/
#include <
libavcodec/avcodec.h
>
#include <
libavformat/avformat.h
>
#include <
libavfilter/buffersink.h
>
#include <
libavfilter/buffersrc.h
>
#include <
libavutil/opt.h
>
#include <
libavutil/pixdesc.h
>
static
AVFormatContext
*
ifmt_ctx
;
static
AVFormatContext
*
ofmt_ctx
;
typedef
struct
FilteringContext
{
AVFilterContext
*
buffersink_ctx
;
AVFilterContext
*
buffersrc_ctx
;
AVFilterGraph
*
filter_graph
;
AVPacket
*
enc_pkt
;
AVFrame
*
filtered_frame
;
}
FilteringContext
;
static
FilteringContext
*
filter_ctx
;
typedef
struct
StreamContext
{
AVCodecContext
*
dec_ctx
;
AVCodecContext
*
enc_ctx
;
AVFrame
*
dec_frame
;
}
StreamContext
;
static
StreamContext
*
stream_ctx
;
static
int
open_input_file
(
const
char
*filename)
{
int
ret;
unsigned
int
i
;
ifmt_ctx
=
NULL
;
if
((ret =
avformat_open_input
(&
ifmt_ctx
, filename,
NULL
,
NULL
)) < 0) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Cannot open input file\n"
);
return
ret;
}
if
((ret =
avformat_find_stream_info
(
ifmt_ctx
,
NULL
)) < 0) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Cannot find stream information\n"
);
return
ret;
}
stream_ctx
=
av_mallocz_array
(
ifmt_ctx
->
nb_streams
,
sizeof
(*
stream_ctx
));
if
(!
stream_ctx
)
return
AVERROR
(ENOMEM);
for
(
i
= 0;
i
<
ifmt_ctx
->
nb_streams
;
i
++) {
AVStream
*stream =
ifmt_ctx
->
streams
[
i
];
AVCodec
*dec =
avcodec_find_decoder
(stream->
codecpar
->
codec_id
);
AVCodecContext
*codec_ctx;
if
(!dec) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Failed to find decoder for stream #%u\n"
,
i
);
return
AVERROR_DECODER_NOT_FOUND
;
}
codec_ctx =
avcodec_alloc_context3
(dec);
if
(!codec_ctx) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Failed to allocate the decoder context for stream #%u\n"
,
i
);
return
AVERROR
(ENOMEM);
}
ret =
avcodec_parameters_to_context
(codec_ctx, stream->
codecpar
);
if
(ret < 0) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Failed to copy decoder parameters to input decoder context "
"for stream #%u\n"
,
i
);
return
ret;
}
/* Reencode video & audio and remux subtitles etc. */
if
(codec_ctx->
codec_type
==
AVMEDIA_TYPE_VIDEO
|| codec_ctx->
codec_type
==
AVMEDIA_TYPE_AUDIO
) {
if
(codec_ctx->
codec_type
==
AVMEDIA_TYPE_VIDEO
)
codec_ctx->
framerate
=
av_guess_frame_rate
(
ifmt_ctx
, stream,
NULL
);
/* Open decoder */
ret =
avcodec_open2
(codec_ctx, dec,
NULL
);
if
(ret < 0) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Failed to open decoder for stream #%u\n"
,
i
);
return
ret;
}
}
stream_ctx
[
i
].
dec_ctx
= codec_ctx;
stream_ctx
[
i
].
dec_frame
=
av_frame_alloc
();
if
(!
stream_ctx
[
i
].dec_frame)
return
AVERROR
(ENOMEM);
}
av_dump_format
(
ifmt_ctx
, 0, filename, 0);
return
0;
}
static
int
open_output_file
(
const
char
*filename)
{
AVStream
*out_stream;
AVStream
*in_stream;
AVCodecContext
*
dec_ctx
, *enc_ctx;
AVCodec
*encoder;
int
ret;
unsigned
int
i
;
ofmt_ctx
=
NULL
;
avformat_alloc_output_context2
(&
ofmt_ctx
,
NULL
,
NULL
, filename);
if
(!
ofmt_ctx
) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Could not create output context\n"
);
return
AVERROR_UNKNOWN
;
}
for
(
i
= 0;
i
<
ifmt_ctx
->
nb_streams
;
i
++) {
out_stream =
avformat_new_stream
(
ofmt_ctx
,
NULL
);
if
(!out_stream) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Failed allocating output stream\n"
);
return
AVERROR_UNKNOWN
;
}
in_stream =
ifmt_ctx
->
streams
[
i
];
dec_ctx
=
stream_ctx
[
i
].
dec_ctx
;
if
(
dec_ctx
->
codec_type
==
AVMEDIA_TYPE_VIDEO
||
dec_ctx
->
codec_type
==
AVMEDIA_TYPE_AUDIO
) {
/* in this example, we choose transcoding to same codec */
encoder =
avcodec_find_encoder
(
dec_ctx
->
codec_id
);
if
(!encoder) {
av_log
(
NULL
,
AV_LOG_FATAL
,
"Necessary encoder not found\n"
);
return
AVERROR_INVALIDDATA
;
}
enc_ctx =
avcodec_alloc_context3
(encoder);
if
(!enc_ctx) {
av_log
(
NULL
,
AV_LOG_FATAL
,
"Failed to allocate the encoder context\n"
);
return
AVERROR
(ENOMEM);
}
/* In this example, we transcode to same properties (picture size,
* sample rate etc.). These properties can be changed for output
* streams easily using filters */
if
(
dec_ctx
->
codec_type
==
AVMEDIA_TYPE_VIDEO
) {
enc_ctx->
height
=
dec_ctx
->
height
;
enc_ctx->
width
=
dec_ctx
->
width
;
enc_ctx->
sample_aspect_ratio
=
dec_ctx
->
sample_aspect_ratio
;
/* take first format from list of supported formats */
if
(encoder->
pix_fmts
)
enc_ctx->
pix_fmt
= encoder->
pix_fmts
[0];
else
enc_ctx->
pix_fmt
=
dec_ctx
->
pix_fmt
;
/* video time_base can be set to whatever is handy and supported by encoder */
enc_ctx->
time_base
=
av_inv_q
(
dec_ctx
->
framerate
);
}
else
{
enc_ctx->
sample_rate
=
dec_ctx
->
sample_rate
;
enc_ctx->
channel_layout
=
dec_ctx
->
channel_layout
;
enc_ctx->
channels
=
av_get_channel_layout_nb_channels
(enc_ctx->
channel_layout
);
/* take first format from list of supported formats */
enc_ctx->
sample_fmt
= encoder->
sample_fmts
[0];
enc_ctx->
time_base
= (
AVRational
){1, enc_ctx->
sample_rate
};
}
if
(
ofmt_ctx
->
oformat
->
flags
&
AVFMT_GLOBALHEADER
)
enc_ctx->
flags
|=
AV_CODEC_FLAG_GLOBAL_HEADER
;
/* Third parameter can be used to pass settings to encoder */
ret =
avcodec_open2
(enc_ctx, encoder,
NULL
);
if
(ret < 0) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Cannot open video encoder for stream #%u\n"
,
i
);
return
ret;
}
ret =
avcodec_parameters_from_context
(out_stream->
codecpar
, enc_ctx);
if
(ret < 0) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Failed to copy encoder parameters to output stream #%u\n"
,
i
);
return
ret;
}
out_stream->
time_base
= enc_ctx->
time_base
;
stream_ctx
[
i
].
enc_ctx
= enc_ctx;
}
else
if
(
dec_ctx
->
codec_type
==
AVMEDIA_TYPE_UNKNOWN
) {
av_log
(
NULL
,
AV_LOG_FATAL
,
"Elementary stream #%d is of unknown type, cannot proceed\n"
,
i
);
return
AVERROR_INVALIDDATA
;
}
else
{
/* if this stream must be remuxed */
ret =
avcodec_parameters_copy
(out_stream->
codecpar
, in_stream->
codecpar
);
if
(ret < 0) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Copying parameters for stream #%u failed\n"
,
i
);
return
ret;
}
out_stream->
time_base
= in_stream->
time_base
;
}
}
av_dump_format
(
ofmt_ctx
, 0, filename, 1);
if
(!(
ofmt_ctx
->
oformat
->
flags
&
AVFMT_NOFILE
)) {
ret =
avio_open
(&
ofmt_ctx
->
pb
, filename,
AVIO_FLAG_WRITE
);
if
(ret < 0) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Could not open output file '%s'"
, filename);
return
ret;
}
}
/* init muxer, write output file header */
ret =
avformat_write_header
(
ofmt_ctx
,
NULL
);
if
(ret < 0) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Error occurred when opening output file\n"
);
return
ret;
}
return
0;
}
static
int
init_filter
(
FilteringContext
* fctx,
AVCodecContext
*
dec_ctx
,
AVCodecContext
*enc_ctx,
const
char
*filter_spec)
{
char
args[512];
int
ret = 0;
const
AVFilter
*buffersrc =
NULL
;
const
AVFilter
*buffersink =
NULL
;
AVFilterContext
*
buffersrc_ctx
=
NULL
;
AVFilterContext
*
buffersink_ctx
=
NULL
;
AVFilterInOut
*
outputs
=
avfilter_inout_alloc
();
AVFilterInOut
*
inputs
=
avfilter_inout_alloc
();
AVFilterGraph
*
filter_graph
=
avfilter_graph_alloc
();
if
(!
outputs
|| !
inputs
|| !
filter_graph
) {
ret =
AVERROR
(ENOMEM);
goto
end;
}
if
(
dec_ctx
->
codec_type
==
AVMEDIA_TYPE_VIDEO
) {
buffersrc =
avfilter_get_by_name
(
"buffer"
);
buffersink =
avfilter_get_by_name
(
"buffersink"
);
if
(!buffersrc || !buffersink) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"filtering source or sink element not found\n"
);
ret =
AVERROR_UNKNOWN
;
goto
end;
}
snprintf
(args,
sizeof
(args),
"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d"
,
dec_ctx
->
width
,
dec_ctx
->
height
,
dec_ctx
->
pix_fmt
,
dec_ctx
->
time_base
.
num
,
dec_ctx
->
time_base
.
den
,
dec_ctx
->
sample_aspect_ratio
.
num
,
dec_ctx
->
sample_aspect_ratio
.
den
);
ret =
avfilter_graph_create_filter
(&
buffersrc_ctx
, buffersrc,
"in"
,
args,
NULL
,
filter_graph
);
if
(ret < 0) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Cannot create buffer source\n"
);
goto
end;
}
ret =
avfilter_graph_create_filter
(&
buffersink_ctx
, buffersink,
"out"
,
NULL
,
NULL
,
filter_graph
);
if
(ret < 0) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Cannot create buffer sink\n"
);
goto
end;
}
ret =
av_opt_set_bin
(
buffersink_ctx
,
"pix_fmts"
,
(
uint8_t
*)&enc_ctx->
pix_fmt
,
sizeof
(enc_ctx->
pix_fmt
),
AV_OPT_SEARCH_CHILDREN
);
if
(ret < 0) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Cannot set output pixel format\n"
);
goto
end;
}
}
else
if
(
dec_ctx
->
codec_type
==
AVMEDIA_TYPE_AUDIO
) {
buffersrc =
avfilter_get_by_name
(
"abuffer"
);
buffersink =
avfilter_get_by_name
(
"abuffersink"
);
if
(!buffersrc || !buffersink) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"filtering source or sink element not found\n"
);
ret =
AVERROR_UNKNOWN
;
goto
end;
}
if
(!
dec_ctx
->
channel_layout
)
dec_ctx
->
channel_layout
=
av_get_default_channel_layout
(
dec_ctx
->
channels
);
snprintf
(args,
sizeof
(args),
"time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%"
PRIx64,
dec_ctx
->
time_base
.
num
,
dec_ctx
->
time_base
.
den
,
dec_ctx
->
sample_rate
,
av_get_sample_fmt_name
(
dec_ctx
->
sample_fmt
),
dec_ctx
->
channel_layout
);
ret =
avfilter_graph_create_filter
(&
buffersrc_ctx
, buffersrc,
"in"
,
args,
NULL
,
filter_graph
);
if
(ret < 0) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Cannot create audio buffer source\n"
);
goto
end;
}
ret =
avfilter_graph_create_filter
(&
buffersink_ctx
, buffersink,
"out"
,
NULL
,
NULL
,
filter_graph
);
if
(ret < 0) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Cannot create audio buffer sink\n"
);
goto
end;
}
ret =
av_opt_set_bin
(
buffersink_ctx
,
"sample_fmts"
,
(
uint8_t
*)&enc_ctx->
sample_fmt
,
sizeof
(enc_ctx->
sample_fmt
),
AV_OPT_SEARCH_CHILDREN
);
if
(ret < 0) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Cannot set output sample format\n"
);
goto
end;
}
ret =
av_opt_set_bin
(
buffersink_ctx
,
"channel_layouts"
,
(
uint8_t
*)&enc_ctx->
channel_layout
,
sizeof
(enc_ctx->
channel_layout
),
AV_OPT_SEARCH_CHILDREN
);
if
(ret < 0) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Cannot set output channel layout\n"
);
goto
end;
}
ret =
av_opt_set_bin
(
buffersink_ctx
,
"sample_rates"
,
(
uint8_t
*)&enc_ctx->
sample_rate
,
sizeof
(enc_ctx->
sample_rate
),
AV_OPT_SEARCH_CHILDREN
);
if
(ret < 0) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Cannot set output sample rate\n"
);
goto
end;
}
}
else
{
ret =
AVERROR_UNKNOWN
;
goto
end;
}
/* Endpoints for the filter graph. */
outputs
->
name
=
av_strdup
(
"in"
);
outputs
->filter_ctx =
buffersrc_ctx
;
outputs
->pad_idx = 0;
outputs
->next =
NULL
;
inputs
->
name
=
av_strdup
(
"out"
);
inputs
->filter_ctx =
buffersink_ctx
;
inputs
->pad_idx = 0;
inputs
->next =
NULL
;
if
(!
outputs
->
name
|| !
inputs
->
name
) {
ret =
AVERROR
(ENOMEM);
goto
end;
}
if
((ret =
avfilter_graph_parse_ptr
(
filter_graph
, filter_spec,
&
inputs
, &
outputs
,
NULL
)) < 0)
goto
end;
if
((ret =
avfilter_graph_config
(
filter_graph
,
NULL
)) < 0)
goto
end;
/* Fill FilteringContext */
fctx->
buffersrc_ctx
=
buffersrc_ctx
;
fctx->
buffersink_ctx
=
buffersink_ctx
;
fctx->
filter_graph
=
filter_graph
;
end:
avfilter_inout_free
(&
inputs
);
avfilter_inout_free
(&
outputs
);
return
ret;
}
static
int
init_filters
(
void
)
{
const
char
*filter_spec;
unsigned
int
i
;
int
ret;
filter_ctx
=
av_malloc_array
(
ifmt_ctx
->
nb_streams
,
sizeof
(*
filter_ctx
));
if
(!
filter_ctx
)
return
AVERROR
(ENOMEM);
for
(
i
= 0;
i
<
ifmt_ctx
->
nb_streams
;
i
++) {
filter_ctx
[
i
].
buffersrc_ctx
=
NULL
;
filter_ctx
[
i
].
buffersink_ctx
=
NULL
;
filter_ctx
[
i
].
filter_graph
=
NULL
;
if
(!(
ifmt_ctx
->
streams
[
i
]->
codecpar
->
codec_type
==
AVMEDIA_TYPE_AUDIO
||
ifmt_ctx
->
streams
[
i
]->
codecpar
->
codec_type
==
AVMEDIA_TYPE_VIDEO
))
continue
;
if
(
ifmt_ctx
->
streams
[
i
]->
codecpar
->
codec_type
==
AVMEDIA_TYPE_VIDEO
)
filter_spec =
"null"
;
/* passthrough (dummy) filter for video */
else
filter_spec =
"anull"
;
/* passthrough (dummy) filter for audio */
ret =
init_filter
(&
filter_ctx
[
i
],
stream_ctx
[
i
].
dec_ctx
,
stream_ctx
[
i
].enc_ctx, filter_spec);
if
(ret)
return
ret;
filter_ctx
[
i
].
enc_pkt
=
av_packet_alloc
();
if
(!
filter_ctx
[
i
].enc_pkt)
return
AVERROR
(ENOMEM);
filter_ctx
[
i
].
filtered_frame
=
av_frame_alloc
();
if
(!
filter_ctx
[
i
].filtered_frame)
return
AVERROR
(ENOMEM);
}
return
0;
}
static
int
encode_write_frame
(
unsigned
int
stream_index,
int
flush
)
{
StreamContext
*stream = &
stream_ctx
[stream_index];
FilteringContext
*
filter
= &
filter_ctx
[stream_index];
AVFrame
*filt_frame =
flush
?
NULL
:
filter
->filtered_frame;
AVPacket
*enc_pkt =
filter
->enc_pkt;
int
ret;
av_log
(
NULL
,
AV_LOG_INFO
,
"Encoding frame\n"
);
/* encode filtered frame */
av_packet_unref
(enc_pkt);
ret =
avcodec_send_frame
(stream->
enc_ctx
, filt_frame);
if
(ret < 0)
return
ret;
while
(ret >= 0) {
ret =
avcodec_receive_packet
(stream->
enc_ctx
, enc_pkt);
if
(ret ==
AVERROR
(EAGAIN) || ret ==
AVERROR_EOF
)
return
0;
/* prepare packet for muxing */
enc_pkt->
stream_index
= stream_index;
av_packet_rescale_ts
(enc_pkt,
stream->
enc_ctx
->
time_base
,
ofmt_ctx
->
streams
[stream_index]->
time_base
);
av_log
(
NULL
,
AV_LOG_DEBUG
,
"Muxing frame\n"
);
/* mux encoded frame */
ret =
av_interleaved_write_frame
(
ofmt_ctx
, enc_pkt);
}
return
ret;
}
static
int
filter_encode_write_frame
(
AVFrame
*
frame
,
unsigned
int
stream_index)
{
FilteringContext
*
filter
= &
filter_ctx
[stream_index];
int
ret;
av_log
(
NULL
,
AV_LOG_INFO
,
"Pushing decoded frame to filters\n"
);
/* push the decoded frame into the filtergraph */
ret =
av_buffersrc_add_frame_flags
(
filter
->buffersrc_ctx,
frame
, 0);
if
(ret < 0) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Error while feeding the filtergraph\n"
);
return
ret;
}
/* pull filtered frames from the filtergraph */
while
(1) {
av_log
(
NULL
,
AV_LOG_INFO
,
"Pulling filtered frame from filters\n"
);
ret =
av_buffersink_get_frame
(
filter
->buffersink_ctx,
filter
->filtered_frame);
if
(ret < 0) {
/* if no more frames for output - returns AVERROR(EAGAIN)
* if flushed and no more frames for output - returns AVERROR_EOF
* rewrite retcode to 0 to show it as normal procedure completion
*/
if
(ret ==
AVERROR
(EAGAIN) || ret ==
AVERROR_EOF
)
ret = 0;
break
;
}
filter
->filtered_frame->pict_type =
AV_PICTURE_TYPE_NONE
;
ret =
encode_write_frame
(stream_index, 0);
av_frame_unref
(
filter
->filtered_frame);
if
(ret < 0)
break
;
}
return
ret;
}
static
int
flush_encoder
(
unsigned
int
stream_index)
{
if
(!(
stream_ctx
[stream_index].enc_ctx->
codec
->
capabilities
&
AV_CODEC_CAP_DELAY
))
return
0;
av_log
(
NULL
,
AV_LOG_INFO
,
"Flushing stream #%u encoder\n"
, stream_index);
return
encode_write_frame
(stream_index, 1);
}
int
main
(
int
argc,
char
**argv)
{
int
ret;
AVPacket
*packet =
NULL
;
unsigned
int
stream_index;
unsigned
int
i
;
if
(argc != 3) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Usage: %s <input file> <output file>\n"
, argv[0]);
return
1;
}
if
((ret =
open_input_file
(argv[1])) < 0)
goto
end;
if
((ret =
open_output_file
(argv[2])) < 0)
goto
end;
if
((ret =
init_filters
()) < 0)
goto
end;
if
(!(packet =
av_packet_alloc
()))
goto
end;
/* read all packets */
while
(1) {
if
((ret =
av_read_frame
(
ifmt_ctx
, packet)) < 0)
break
;
stream_index = packet->
stream_index
;
av_log
(
NULL
,
AV_LOG_DEBUG
,
"Demuxer gave frame of stream_index %u\n"
,
stream_index);
if
(
filter_ctx
[stream_index].
filter_graph
) {
StreamContext
*stream = &
stream_ctx
[stream_index];
av_log
(
NULL
,
AV_LOG_DEBUG
,
"Going to reencode&filter the frame\n"
);
av_packet_rescale_ts
(packet,
ifmt_ctx
->
streams
[stream_index]->
time_base
,
stream->
dec_ctx
->
time_base
);
ret =
avcodec_send_packet
(stream->
dec_ctx
, packet);
if
(ret < 0) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Decoding failed\n"
);
break
;
}
while
(ret >= 0) {
ret =
avcodec_receive_frame
(stream->
dec_ctx
, stream->
dec_frame
);
if
(ret ==
AVERROR_EOF
|| ret ==
AVERROR
(EAGAIN))
break
;
else
if
(ret < 0)
goto
end;
stream->
dec_frame
->
pts
= stream->
dec_frame
->
best_effort_timestamp
;
ret =
filter_encode_write_frame
(stream->
dec_frame
, stream_index);
if
(ret < 0)
goto
end;
}
}
else
{
/* remux this frame without reencoding */
av_packet_rescale_ts
(packet,
ifmt_ctx
->
streams
[stream_index]->
time_base
,
ofmt_ctx
->
streams
[stream_index]->
time_base
);
ret =
av_interleaved_write_frame
(
ofmt_ctx
, packet);
if
(ret < 0)
goto
end;
}
av_packet_unref
(packet);
}
/* flush filters and encoders */
for
(
i
= 0;
i
<
ifmt_ctx
->
nb_streams
;
i
++) {
/* flush filter */
if
(!
filter_ctx
[
i
].
filter_graph
)
continue
;
ret =
filter_encode_write_frame
(
NULL
,
i
);
if
(ret < 0) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Flushing filter failed\n"
);
goto
end;
}
/* flush encoder */
ret =
flush_encoder
(
i
);
if
(ret < 0) {
av_log
(
NULL
,
AV_LOG_ERROR
,
"Flushing encoder failed\n"
);
goto
end;
}
}
av_write_trailer
(
ofmt_ctx
);
end:
av_packet_free
(&packet);
for
(
i
= 0;
i
<
ifmt_ctx
->
nb_streams
;
i
++) {
avcodec_free_context
(&
stream_ctx
[
i
].
dec_ctx
);
if
(
ofmt_ctx
&&
ofmt_ctx
->
nb_streams
>
i
&&
ofmt_ctx
->
streams
[
i
] &&
stream_ctx
[
i
].
enc_ctx
)
avcodec_free_context
(&
stream_ctx
[
i
].enc_ctx);
if
(
filter_ctx
&&
filter_ctx
[
i
].
filter_graph
) {
avfilter_graph_free
(&
filter_ctx
[
i
].
filter_graph
);
av_packet_free
(&
filter_ctx
[
i
].enc_pkt);
av_frame_free
(&
filter_ctx
[
i
].filtered_frame);
}
av_frame_free
(&
stream_ctx
[
i
].dec_frame);
}
av_free
(
filter_ctx
);
av_free
(
stream_ctx
);
avformat_close_input
(&
ifmt_ctx
);
if
(
ofmt_ctx
&& !(
ofmt_ctx
->
oformat
->
flags
&
AVFMT_NOFILE
))
avio_closep
(&
ofmt_ctx
->
pb
);
avformat_free_context
(
ofmt_ctx
);
if
(ret < 0)
av_log
(
NULL
,
AV_LOG_ERROR
,
"Error occurred: %s\n"
,
av_err2str
(ret));
return
ret ? 1 : 0;
}
flush
static void flush(AVCodecContext *avctx)
Definition:
aacdec_template.c:592
inputs
static const AVFilterPad inputs[]
Definition:
af_acontrast.c:193
outputs
static const AVFilterPad outputs[]
Definition:
af_acontrast.c:203
uint8_t
uint8_t
Definition:
audio_convert.c:194
avcodec.h
Libavcodec external API header.
avformat.h
Main libavformat public API header.
avformat_alloc_output_context2
int avformat_alloc_output_context2(AVFormatContext **ctx, ff_const59 AVOutputFormat *oformat, const char *format_name, const char *filename)
Allocate an AVFormatContext for an output format.
Definition:
mux.c:136
AVFMT_NOFILE
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition:
avformat.h:458
AVFMT_GLOBALHEADER
#define AVFMT_GLOBALHEADER
Format wants global header.
Definition:
avformat.h:461
avio_open
int avio_open(AVIOContext **s, const char *url, int flags)
Create and initialize a AVIOContext for accessing the resource indicated by url.
Definition:
aviobuf.c:1140
AVIO_FLAG_WRITE
#define AVIO_FLAG_WRITE
write-only
Definition:
avio.h:675
avio_closep
int avio_closep(AVIOContext **s)
Close the resource accessed by the AVIOContext *s, free it and set the pointer pointing to it to NULL...
Definition:
aviobuf.c:1195
buffersink.h
memory buffer sink API for audio and video
buffersrc.h
Memory buffer source API.
filter
static av_always_inline void filter(int16_t *output, ptrdiff_t out_stride, const int16_t *low, ptrdiff_t low_stride, const int16_t *high, ptrdiff_t high_stride, int len, int clip)
Definition:
cfhddsp.c:27
avcodec_parameters_copy
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Copy the contents of src to dst.
Definition:
codec_par.c:72
NULL
#define NULL
Definition:
coverity.c:32
frame
static AVFrame * frame
Definition:
demuxing_decoding.c:53
filter_graph
AVFilterGraph * filter_graph
Definition:
filtering_audio.c:46
buffersink_ctx
AVFilterContext * buffersink_ctx
Definition:
filtering_audio.c:44
buffersrc_ctx
AVFilterContext * buffersrc_ctx
Definition:
filtering_audio.c:45
dec_ctx
static AVCodecContext * dec_ctx
Definition:
filtering_audio.c:43
AV_OPT_SEARCH_CHILDREN
#define AV_OPT_SEARCH_CHILDREN
Search in possible children of the given object first.
Definition:
opt.h:560
av_get_channel_layout_nb_channels
int av_get_channel_layout_nb_channels(uint64_t channel_layout)
Return the number of channels in the channel layout.
Definition:
channel_layout.c:226
av_get_default_channel_layout
int64_t av_get_default_channel_layout(int nb_channels)
Return default channel layout for a given number of channels.
Definition:
channel_layout.c:231
avcodec_parameters_from_context
int avcodec_parameters_from_context(AVCodecParameters *par, const AVCodecContext *codec)
Fill the parameters struct based on the values from the supplied codec context.
Definition:
codec_par.c:90
avcodec_open2
int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
Initialize the AVCodecContext to use the given AVCodec.
Definition:
avcodec.c:144
avcodec_find_decoder
AVCodec * avcodec_find_decoder(enum AVCodecID id)
Find a registered decoder with a matching codec ID.
Definition:
allcodecs.c:946
AV_CODEC_CAP_DELAY
#define AV_CODEC_CAP_DELAY
Encoder or decoder requires flushing with NULL input at the end in order to give the complete and cor...
Definition:
codec.h:77
AV_CODEC_FLAG_GLOBAL_HEADER
#define AV_CODEC_FLAG_GLOBAL_HEADER
Place global headers in extradata instead of every keyframe.
Definition:
avcodec.h:329
avcodec_find_encoder
AVCodec * avcodec_find_encoder(enum AVCodecID id)
Find a registered encoder with a matching codec ID.
Definition:
allcodecs.c:941
avcodec_parameters_to_context
int avcodec_parameters_to_context(AVCodecContext *codec, const AVCodecParameters *par)
Fill the codec context based on the values from the supplied codec parameters.
Definition:
codec_par.c:147
avcodec_alloc_context3
AVCodecContext * avcodec_alloc_context3(const AVCodec *codec)
Allocate an AVCodecContext and set its fields to default values.
Definition:
options.c:173
avcodec_free_context
void avcodec_free_context(AVCodecContext **avctx)
Free the codec context and everything associated with it and write NULL to the provided pointer.
Definition:
options.c:188
avcodec_receive_frame
int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)
Return decoded output data from a decoder.
Definition:
decode.c:652
avcodec_send_packet
int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt)
Supply raw packet data as input to a decoder.
Definition:
decode.c:589
avcodec_receive_packet
int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
Read encoded data from the encoder.
Definition:
encode.c:395
avcodec_send_frame
int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame)
Supply a raw video or audio frame to the encoder.
Definition:
encode.c:364
av_packet_free
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition:
avpacket.c:75
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition:
avpacket.c:634
av_packet_alloc
AVPacket * av_packet_alloc(void)
Allocate an AVPacket and set its fields to default values.
Definition:
avpacket.c:64
av_packet_rescale_ts
void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb)
Convert valid timing fields (timestamps / durations) in a packet from one timebase to another.
Definition:
avpacket.c:737
avformat_free_context
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition:
utils.c:4436
avformat_new_stream
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition:
utils.c:4509
av_read_frame
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
Return the next frame of a stream.
Definition:
utils.c:1741
avformat_find_stream_info
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
Read packets of a media file to get stream information.
Definition:
utils.c:3602
avformat_close_input
void avformat_close_input(AVFormatContext **s)
Close an opened input AVFormatContext.
Definition:
utils.c:4481
avformat_open_input
int avformat_open_input(AVFormatContext **ps, const char *url, ff_const59 AVInputFormat *fmt, AVDictionary **options)
Open an input stream and read the header.
Definition:
utils.c:512
avformat_write_header
av_warn_unused_result int avformat_write_header(AVFormatContext *s, AVDictionary **options)
Allocate the stream private data and write the stream header to an output media file.
Definition:
mux.c:506
av_interleaved_write_frame
int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file ensuring correct interleaving.
Definition:
mux.c:1259
av_write_trailer
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
Definition:
mux.c:1274
av_guess_frame_rate
AVRational av_guess_frame_rate(AVFormatContext *ctx, AVStream *stream, AVFrame *frame)
Guess the frame rate, based on both the container and codec information.
Definition:
utils.c:5142
av_dump_format
void av_dump_format(AVFormatContext *ic, int index, const char *url, int is_output)
Print detailed information about the input or output format, such as duration, bitrate,...
Definition:
dump.c:640
av_buffersink_get_frame
int attribute_align_arg av_buffersink_get_frame(AVFilterContext *ctx, AVFrame *frame)
Get a frame with filtered data from sink and put it in frame.
Definition:
buffersink.c:88
av_buffersrc_add_frame_flags
int attribute_align_arg av_buffersrc_add_frame_flags(AVFilterContext *ctx, AVFrame *frame, int flags)
Add a frame to the buffer source.
Definition:
buffersrc.c:166
avfilter_graph_config
int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx)
Check validity and configure all the links and formats in the graph.
Definition:
avfiltergraph.c:1218
avfilter_inout_free
void avfilter_inout_free(AVFilterInOut **inout)
Free the supplied list of AVFilterInOut and set *inout to NULL.
Definition:
graphparser.c:212
avfilter_graph_parse_ptr
int avfilter_graph_parse_ptr(AVFilterGraph *graph, const char *filters, AVFilterInOut **inputs, AVFilterInOut **outputs, void *log_ctx)
Add a graph described by a string to a graph.
Definition:
graphparser.c:549
avfilter_graph_alloc
AVFilterGraph * avfilter_graph_alloc(void)
Allocate a filter graph.
Definition:
avfiltergraph.c:83
avfilter_inout_alloc
AVFilterInOut * avfilter_inout_alloc(void)
Allocate a single AVFilterInOut entry.
Definition:
graphparser.c:207
avfilter_graph_free
void avfilter_graph_free(AVFilterGraph **graph)
Free a graph, destroy its links, and set *graph to NULL.
Definition:
avfiltergraph.c:120
avfilter_graph_create_filter
int avfilter_graph_create_filter(AVFilterContext **filt_ctx, const AVFilter *filt, const char *name, const char *args, void *opaque, AVFilterGraph *graph_ctx)
Create and add a filter instance into an existing graph.
Definition:
avfiltergraph.c:142
avfilter_get_by_name
const AVFilter * avfilter_get_by_name(const char *name)
Get a filter definition matching the given name.
Definition:
allfilters.c:545
AVERROR_DECODER_NOT_FOUND
#define AVERROR_DECODER_NOT_FOUND
Decoder not found.
Definition:
error.h:52
AVERROR_UNKNOWN
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition:
error.h:71
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition:
error.h:59
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition:
error.h:55
av_err2str
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition:
error.h:119
AVERROR
#define AVERROR(e)
Definition:
error.h:43
av_frame_unref
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition:
frame.c:553
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition:
frame.c:203
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition:
frame.c:190
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition:
log.h:215
AV_LOG_FATAL
#define AV_LOG_FATAL
Something went wrong and recovery is not possible.
Definition:
log.h:188
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition:
log.h:205
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition:
log.h:194
av_inv_q
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition:
rational.h:159
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition:
mem.c:253
av_mallocz_array
void * av_mallocz_array(size_t nmemb, size_t size)
Allocate a memory block for an array with av_mallocz().
Definition:
mem.c:190
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition:
avutil.h:202
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition:
avutil.h:201
AVMEDIA_TYPE_UNKNOWN
@ AVMEDIA_TYPE_UNKNOWN
Usually treated as AVMEDIA_TYPE_DATA.
Definition:
avutil.h:200
AV_PICTURE_TYPE_NONE
@ AV_PICTURE_TYPE_NONE
Undefined.
Definition:
avutil.h:273
av_get_sample_fmt_name
const char * av_get_sample_fmt_name(enum AVSampleFormat sample_fmt)
Return the name of sample_fmt, or NULL if sample_fmt is not recognized.
Definition:
samplefmt.c:49
av_opt_set_bin
int av_opt_set_bin(void *obj, const char *name, const uint8_t *val, int len, int search_flags)
Definition:
opt.c:601
i
int i
Definition:
input.c:407
opt.h
AVOptions.
pixdesc.h
snprintf
#define snprintf
Definition:
snprintf.h:34
AVCodecContext
main external API structure.
Definition:
avcodec.h:536
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition:
avcodec.h:746
AVCodecContext::height
int height
Definition:
avcodec.h:709
AVCodecContext::width
int width
picture width / height.
Definition:
avcodec.h:709
AVCodecContext::sample_fmt
enum AVSampleFormat sample_fmt
audio sample format
Definition:
avcodec.h:1204
AVCodecContext::codec_type
enum AVMediaType codec_type
Definition:
avcodec.h:544
AVCodecContext::framerate
AVRational framerate
Definition:
avcodec.h:2075
AVCodecContext::sample_aspect_ratio
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown) That is the width of a pixel divided by the height of the pixel.
Definition:
avcodec.h:915
AVCodecContext::codec
const struct AVCodec * codec
Definition:
avcodec.h:545
AVCodecContext::sample_rate
int sample_rate
samples per second
Definition:
avcodec.h:1196
AVCodecContext::time_base
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition:
avcodec.h:659
AVCodecContext::flags
int flags
AV_CODEC_FLAG_*.
Definition:
avcodec.h:616
AVCodecContext::channels
int channels
number of audio channels
Definition:
avcodec.h:1197
AVCodecContext::codec_id
enum AVCodecID codec_id
Definition:
avcodec.h:546
AVCodecContext::channel_layout
uint64_t channel_layout
Audio channel layout.
Definition:
avcodec.h:1247
AVCodecParameters::codec_type
enum AVMediaType codec_type
General type of the encoded data.
Definition:
codec_par.h:56
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition:
codec_par.h:60
AVCodec
AVCodec.
Definition:
codec.h:197
AVCodec::sample_fmts
enum AVSampleFormat * sample_fmts
array of supported sample formats, or NULL if unknown, array is terminated by -1
Definition:
codec.h:220
AVCodec::pix_fmts
enum AVPixelFormat * pix_fmts
array of supported pixel formats, or NULL if unknown, array is terminated by -1
Definition:
codec.h:218
AVCodec::capabilities
int capabilities
Codec capabilities.
Definition:
codec.h:216
AVFilterContext
An instance of a filter.
Definition:
avfilter.h:341
AVFilterGraph
Definition:
avfilter.h:850
AVFilterInOut
A linked-list of the inputs/outputs of the filter chain.
Definition:
avfilter.h:1013
AVFilterPad::name
const char * name
Pad name.
Definition:
internal.h:60
AVFilter
Filter definition.
Definition:
avfilter.h:145
AVFormatContext
Format I/O context.
Definition:
avformat.h:1232
AVFormatContext::nb_streams
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition:
avformat.h:1288
AVFormatContext::pb
AVIOContext * pb
I/O context.
Definition:
avformat.h:1274
AVFormatContext::oformat
ff_const59 struct AVOutputFormat * oformat
The output container format.
Definition:
avformat.h:1251
AVFormatContext::streams
AVStream ** streams
A list of all streams in the file.
Definition:
avformat.h:1300
AVFrame
This structure describes decoded (raw) audio or video data.
Definition:
frame.h:318
AVFrame::pts
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition:
frame.h:411
AVFrame::best_effort_timestamp
int64_t best_effort_timestamp
frame timestamp estimated using various heuristics, in stream time base
Definition:
frame.h:582
AVOutputFormat::flags
int flags
can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_GLOBALHEADER, AVFMT_NOTIMESTAMPS,...
Definition:
avformat.h:510
AVPacket
This structure stores compressed data.
Definition:
packet.h:346
AVPacket::stream_index
int stream_index
Definition:
packet.h:371
AVRational
Rational number (pair of numerator and denominator).
Definition:
rational.h:58
AVRational::num
int num
Numerator.
Definition:
rational.h:59
AVRational::den
int den
Denominator.
Definition:
rational.h:60
AVStream
Stream structure.
Definition:
avformat.h:873
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition:
avformat.h:1038
AVStream::time_base
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition:
avformat.h:902
FilteringContext
Definition:
transcoding.c:40
FilteringContext::enc_pkt
AVPacket * enc_pkt
Definition:
transcoding.c:45
FilteringContext::buffersrc_ctx
AVFilterContext * buffersrc_ctx
Definition:
transcoding.c:42
FilteringContext::buffersink_ctx
AVFilterContext * buffersink_ctx
Definition:
transcoding.c:41
FilteringContext::filter_graph
AVFilterGraph * filter_graph
Definition:
transcoding.c:43
FilteringContext::filtered_frame
AVFrame * filtered_frame
Definition:
transcoding.c:46
StreamContext
Definition:
transcoding.c:50
StreamContext::dec_frame
AVFrame * dec_frame
Definition:
transcoding.c:54
StreamContext::dec_ctx
AVCodecContext * dec_ctx
Definition:
transcoding.c:51
StreamContext::enc_ctx
AVCodecContext * enc_ctx
Definition:
transcoding.c:52
av_free
#define av_free(p)
Definition:
tableprint_vlc.h:34
av_malloc_array
#define av_malloc_array(a, b)
Definition:
tableprint_vlc.h:32
av_log
#define av_log(a,...)
Definition:
tableprint_vlc.h:28
init_filters
static int init_filters(void)
Definition:
transcoding.c:384
stream_ctx
static StreamContext * stream_ctx
Definition:
transcoding.c:56
encode_write_frame
static int encode_write_frame(unsigned int stream_index, int flush)
Definition:
transcoding.c:422
ifmt_ctx
static AVFormatContext * ifmt_ctx
Definition:
transcoding.c:38
filter_encode_write_frame
static int filter_encode_write_frame(AVFrame *frame, unsigned int stream_index)
Definition:
transcoding.c:459
main
int main(int argc, char **argv)
Definition:
transcoding.c:508
init_filter
static int init_filter(FilteringContext *fctx, AVCodecContext *dec_ctx, AVCodecContext *enc_ctx, const char *filter_spec)
Definition:
transcoding.c:235
filter_ctx
static FilteringContext * filter_ctx
Definition:
transcoding.c:48
ofmt_ctx
static AVFormatContext * ofmt_ctx
Definition:
transcoding.c:39
open_output_file
static int open_output_file(const char *filename)
Definition:
transcoding.c:120
open_input_file
static int open_input_file(const char *filename)
Definition:
transcoding.c:58
flush_encoder
static int flush_encoder(unsigned int stream_index)
Definition:
transcoding.c:498
Generated on Sun May 18 2025 06:58:54 for FFmpeg by
1.9.1