FFmpeg
5.1.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/channel_layout.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_calloc
(
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];
const
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;
const
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
;
ret =
av_channel_layout_copy
(&enc_ctx->
ch_layout
, &
dec_ctx
->
ch_layout
);
if
(ret < 0)
return
ret;
/* 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
) {
char
buf[64];
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
->
ch_layout
.
order
==
AV_CHANNEL_ORDER_UNSPEC
)
av_channel_layout_default
(&
dec_ctx
->
ch_layout
,
dec_ctx
->
ch_layout
.
nb_channels
);
av_channel_layout_describe
(&
dec_ctx
->
ch_layout
, buf,
sizeof
(buf));
snprintf(args,
sizeof
(args),
"time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=%s"
,
dec_ctx
->
time_base
.
num
,
dec_ctx
->
time_base
.
den
,
dec_ctx
->
sample_rate
,
av_get_sample_fmt_name
(
dec_ctx
->
sample_fmt
),
buf);
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;
}
av_channel_layout_describe
(&enc_ctx->
ch_layout
, buf,
sizeof
(buf));
ret =
av_opt_set
(
buffersink_ctx
,
"ch_layouts"
,
buf,
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;
}
avcodec.h
Libavcodec external API header.
avformat.h
Main libavformat public API header.
AVFMT_NOFILE
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition:
avformat.h:470
AVFMT_GLOBALHEADER
#define AVFMT_GLOBALHEADER
Format wants global header.
Definition:
avformat.h:480
avformat_alloc_output_context2
int avformat_alloc_output_context2(AVFormatContext **ctx, const AVOutputFormat *oformat, const char *format_name, const char *filename)
Allocate an AVFormatContext for an output format.
avio_open
int avio_open(AVIOContext **s, const char *url, int flags)
Create and initialize a AVIOContext for accessing the resource indicated by url.
AVIO_FLAG_WRITE
#define AVIO_FLAG_WRITE
write-only
Definition:
avio.h:629
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...
buffersink.h
memory buffer sink API for audio and video
buffersrc.h
Memory buffer source API.
channel_layout.h
audio channel layout utility functions
avcodec_parameters_copy
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Copy the contents of src to dst.
frame
static AVFrame * frame
Definition:
demuxing_decoding.c:54
filter_graph
AVFilterGraph * filter_graph
Definition:
filtering_audio.c:47
buffersink_ctx
AVFilterContext * buffersink_ctx
Definition:
filtering_audio.c:45
buffersrc_ctx
AVFilterContext * buffersrc_ctx
Definition:
filtering_audio.c:46
dec_ctx
static AVCodecContext * dec_ctx
Definition:
filtering_audio.c:44
AV_OPT_SEARCH_CHILDREN
#define AV_OPT_SEARCH_CHILDREN
Search in possible children of the given object first.
Definition:
opt.h:563
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.
avcodec_open2
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
Initialize the AVCodecContext to use the given AVCodec.
avcodec_alloc_context3
AVCodecContext * avcodec_alloc_context3(const AVCodec *codec)
Allocate an AVCodecContext and set its fields to default values.
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:82
avcodec_find_decoder
const AVCodec * avcodec_find_decoder(enum AVCodecID id)
Find a registered decoder with a matching codec ID.
avcodec_find_encoder
const AVCodec * avcodec_find_encoder(enum AVCodecID id)
Find a registered encoder with a matching codec ID.
AV_CODEC_FLAG_GLOBAL_HEADER
#define AV_CODEC_FLAG_GLOBAL_HEADER
Place global headers in extradata instead of every keyframe.
Definition:
avcodec.h:274
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.
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.
avcodec_receive_frame
int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)
Return decoded output data from a decoder.
avcodec_send_packet
int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt)
Supply raw packet data as input to a decoder.
avcodec_receive_packet
int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
Read encoded data from the encoder.
avcodec_send_frame
int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame)
Supply a raw video or audio frame to the encoder.
av_packet_free
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
av_packet_alloc
AVPacket * av_packet_alloc(void)
Allocate an AVPacket and set its fields to default values.
av_packet_rescale_ts
void av_packet_rescale_ts(AVPacket *pkt, AVRational tb_src, AVRational tb_dst)
Convert valid timing fields (timestamps / durations) in a packet from one timebase to another.
avformat_new_stream
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
avformat_free_context
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
av_read_frame
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
Return the next frame of a stream.
avformat_open_input
int avformat_open_input(AVFormatContext **ps, const char *url, const AVInputFormat *fmt, AVDictionary **options)
Open an input stream and read the header.
avformat_find_stream_info
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
Read packets of a media file to get stream information.
avformat_close_input
void avformat_close_input(AVFormatContext **s)
Close an opened input AVFormatContext.
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.
av_interleaved_write_frame
int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file ensuring correct interleaving.
av_write_trailer
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
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.
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,...
av_buffersink_get_frame
int av_buffersink_get_frame(AVFilterContext *ctx, AVFrame *frame)
Get a frame with filtered data from sink and put it in frame.
av_buffersrc_add_frame_flags
av_warn_unused_result int av_buffersrc_add_frame_flags(AVFilterContext *buffer_src, AVFrame *frame, int flags)
Add a frame to the buffer source.
avfilter_graph_config
int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx)
Check validity and configure all the links and formats in the graph.
avfilter_get_by_name
const AVFilter * avfilter_get_by_name(const char *name)
Get a filter definition matching the given name.
avfilter_inout_free
void avfilter_inout_free(AVFilterInOut **inout)
Free the supplied list of AVFilterInOut and set *inout to NULL.
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.
avfilter_graph_free
void avfilter_graph_free(AVFilterGraph **graph)
Free a graph, destroy its links, and set *graph to NULL.
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.
avfilter_inout_alloc
AVFilterInOut * avfilter_inout_alloc(void)
Allocate a single AVFilterInOut entry.
avfilter_graph_alloc
AVFilterGraph * avfilter_graph_alloc(void)
Allocate a filter graph.
av_channel_layout_default
void av_channel_layout_default(AVChannelLayout *ch_layout, int nb_channels)
Get the default channel layout for a given number of channels.
av_channel_layout_describe
int av_channel_layout_describe(const AVChannelLayout *channel_layout, char *buf, size_t buf_size)
Get a human-readable string describing the channel layout properties.
av_channel_layout_copy
int av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src)
Make a copy of a channel layout.
AV_CHANNEL_ORDER_UNSPEC
@ AV_CHANNEL_ORDER_UNSPEC
Only the channel count is specified, without any further information about the channel order.
Definition:
channel_layout.h:106
AVERROR_DECODER_NOT_FOUND
#define AVERROR_DECODER_NOT_FOUND
Decoder not found.
Definition:
error.h:54
AVERROR_UNKNOWN
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition:
error.h:73
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition:
error.h:61
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition:
error.h:57
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:121
AVERROR
#define AVERROR(e)
Definition:
error.h:45
av_frame_unref
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition:
log.h:201
AV_LOG_FATAL
#define AV_LOG_FATAL
Something went wrong and recovery is not possible.
Definition:
log.h:174
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition:
log.h:191
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition:
log.h:180
av_log
void av_log(void *avcl, int level, const char *fmt,...) av_printf_format(3
Send the specified message to the log if the level is less than or equal to the current av_log_level.
av_inv_q
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition:
rational.h:159
av_free
void av_free(void *ptr)
Free a memory block which has been allocated with a function of av_malloc() or av_realloc() family.
av_strdup
char * av_strdup(const char *s) av_malloc_attrib
Duplicate a string.
av_calloc
void * av_calloc(size_t nmemb, size_t size) av_malloc_attrib
Allocate a memory block for an array with av_mallocz().
av_malloc_array
void * av_malloc_array(size_t nmemb, size_t size)
Allocate a memory block for an array with av_malloc().
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.
av_opt_set
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
av_opt_set_bin
int av_opt_set_bin(void *obj, const char *name, const uint8_t *val, int size, int search_flags)
opt.h
AVOptions.
pixdesc.h
AVChannelLayout::order
enum AVChannelOrder order
Channel order used in this layout.
Definition:
channel_layout.h:295
AVChannelLayout::nb_channels
int nb_channels
Number of channels in this layout.
Definition:
channel_layout.h:300
AVCodecContext
main external API structure.
Definition:
avcodec.h:389
AVCodecContext::pix_fmt
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition:
avcodec.h:599
AVCodecContext::height
int height
Definition:
avcodec.h:562
AVCodecContext::width
int width
picture width / height.
Definition:
avcodec.h:562
AVCodecContext::ch_layout
AVChannelLayout ch_layout
Audio channel layout.
Definition:
avcodec.h:2056
AVCodecContext::sample_fmt
enum AVSampleFormat sample_fmt
audio sample format
Definition:
avcodec.h:1014
AVCodecContext::codec_type
enum AVMediaType codec_type
Definition:
avcodec.h:397
AVCodecContext::framerate
AVRational framerate
Definition:
avcodec.h:1732
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:759
AVCodecContext::codec
const struct AVCodec * codec
Definition:
avcodec.h:398
AVCodecContext::sample_rate
int sample_rate
samples per second
Definition:
avcodec.h:998
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:512
AVCodecContext::flags
int flags
AV_CODEC_FLAG_*.
Definition:
avcodec.h:469
AVCodecContext::codec_id
enum AVCodecID codec_id
Definition:
avcodec.h:399
AVCodecParameters::codec_type
enum AVMediaType codec_type
General type of the encoded data.
Definition:
codec_par.h:57
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition:
codec_par.h:61
AVCodec
AVCodec.
Definition:
codec.h:196
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:215
AVFilterContext
An instance of a filter.
Definition:
avfilter.h:408
AVFilterGraph
Definition:
avfilter.h:871
AVFilterInOut
A linked-list of the inputs/outputs of the filter chain.
Definition:
avfilter.h:1031
AVFilterInOut::filter_ctx
AVFilterContext * filter_ctx
filter context associated to this input/output
Definition:
avfilter.h:1036
AVFilterInOut::pad_idx
int pad_idx
index of the filt_ctx pad to use for linking
Definition:
avfilter.h:1039
AVFilterInOut::name
char * name
unique name for this input/output in the list
Definition:
avfilter.h:1033
AVFilterInOut::next
struct AVFilterInOut * next
next input/input in the list, NULL if this is the last
Definition:
avfilter.h:1042
AVFilter
Filter definition.
Definition:
avfilter.h:171
AVFormatContext
Format I/O context.
Definition:
avformat.h:1213
AVFormatContext::nb_streams
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition:
avformat.h:1269
AVFormatContext::pb
AVIOContext * pb
I/O context.
Definition:
avformat.h:1255
AVFormatContext::oformat
const struct AVOutputFormat * oformat
The output container format.
Definition:
avformat.h:1232
AVFormatContext::streams
AVStream ** streams
A list of all streams in the file.
Definition:
avformat.h:1281
AVFrame
This structure describes decoded (raw) audio or video data.
Definition:
frame.h:325
AVFrame::pts
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition:
frame.h:432
AVFrame::best_effort_timestamp
int64_t best_effort_timestamp
frame timestamp estimated using various heuristics, in stream time base
Definition:
frame.h:598
AVFrame::pict_type
enum AVPictureType pict_type
Picture type of the frame.
Definition:
frame.h:422
AVOutputFormat::flags
int flags
can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_GLOBALHEADER, AVFMT_NOTIMESTAMPS,...
Definition:
avformat.h:529
AVPacket
This structure stores compressed data.
Definition:
packet.h:351
AVPacket::stream_index
int stream_index
Definition:
packet.h:376
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:948
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition:
avformat.h:1108
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:978
FilteringContext
Definition:
transcoding.c:41
FilteringContext::enc_pkt
AVPacket * enc_pkt
Definition:
transcoding.c:46
FilteringContext::buffersrc_ctx
AVFilterContext * buffersrc_ctx
Definition:
transcoding.c:43
FilteringContext::buffersink_ctx
AVFilterContext * buffersink_ctx
Definition:
transcoding.c:42
FilteringContext::filter_graph
AVFilterGraph * filter_graph
Definition:
transcoding.c:44
FilteringContext::filtered_frame
AVFrame * filtered_frame
Definition:
transcoding.c:47
StreamContext
Definition:
transcoding.c:51
StreamContext::dec_frame
AVFrame * dec_frame
Definition:
transcoding.c:55
StreamContext::dec_ctx
AVCodecContext * dec_ctx
Definition:
transcoding.c:52
StreamContext::enc_ctx
AVCodecContext * enc_ctx
Definition:
transcoding.c:53
init_filters
static int init_filters(void)
Definition:
transcoding.c:387
stream_ctx
static StreamContext * stream_ctx
Definition:
transcoding.c:57
encode_write_frame
static int encode_write_frame(unsigned int stream_index, int flush)
Definition:
transcoding.c:425
ifmt_ctx
static AVFormatContext * ifmt_ctx
Definition:
transcoding.c:39
filter_encode_write_frame
static int filter_encode_write_frame(AVFrame *frame, unsigned int stream_index)
Definition:
transcoding.c:462
main
int main(int argc, char **argv)
Definition:
transcoding.c:511
init_filter
static int init_filter(FilteringContext *fctx, AVCodecContext *dec_ctx, AVCodecContext *enc_ctx, const char *filter_spec)
Definition:
transcoding.c:237
filter_ctx
static FilteringContext * filter_ctx
Definition:
transcoding.c:49
ofmt_ctx
static AVFormatContext * ofmt_ctx
Definition:
transcoding.c:40
open_output_file
static int open_output_file(const char *filename)
Definition:
transcoding.c:121
open_input_file
static int open_input_file(const char *filename)
Definition:
transcoding.c:59
flush_encoder
static int flush_encoder(unsigned int stream_index)
Definition:
transcoding.c:501
Generated by
1.9.4