Commit d10b1a20 authored by Clément Bœsch's avatar Clément Bœsch

doc/examples/demuxing: show how to use the reference counting system.

parent 405ceb18
...@@ -53,6 +53,18 @@ static AVPacket pkt; ...@@ -53,6 +53,18 @@ static AVPacket pkt;
static int video_frame_count = 0; static int video_frame_count = 0;
static int audio_frame_count = 0; static int audio_frame_count = 0;
/* The different ways of decoding and managing data memory. You are not
* supposed to support all the modes in your application but pick the one most
* appropriate to your needs. Look for the use of api_mode in this example to
* see what are the differences of API usage between them */
enum {
API_MODE_OLD = 0, /* old method, deprecated */
API_MODE_NEW_API_REF_COUNT = 1, /* new method, using the frame reference counting */
API_MODE_NEW_API_NO_REF_COUNT = 2, /* new method, without reference counting */
};
static int api_mode = API_MODE_OLD;
static int decode_packet(int *got_frame, int cached) static int decode_packet(int *got_frame, int cached)
{ {
int ret = 0; int ret = 0;
...@@ -115,6 +127,11 @@ static int decode_packet(int *got_frame, int cached) ...@@ -115,6 +127,11 @@ static int decode_packet(int *got_frame, int cached)
} }
} }
/* If we use the new API with reference counting, we own the data and need
* to de-reference it when we don't use it anymore */
if (*got_frame && api_mode == API_MODE_NEW_API_REF_COUNT)
av_frame_unref(frame);
return decoded; return decoded;
} }
...@@ -125,6 +142,7 @@ static int open_codec_context(int *stream_idx, ...@@ -125,6 +142,7 @@ static int open_codec_context(int *stream_idx,
AVStream *st; AVStream *st;
AVCodecContext *dec_ctx = NULL; AVCodecContext *dec_ctx = NULL;
AVCodec *dec = NULL; AVCodec *dec = NULL;
AVDictionary *opts = NULL;
ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0); ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0);
if (ret < 0) { if (ret < 0) {
...@@ -144,7 +162,10 @@ static int open_codec_context(int *stream_idx, ...@@ -144,7 +162,10 @@ static int open_codec_context(int *stream_idx,
return ret; return ret;
} }
if ((ret = avcodec_open2(dec_ctx, dec, NULL)) < 0) { /* Init the decoders, with or without reference counting */
if (api_mode == API_MODE_NEW_API_REF_COUNT)
av_dict_set(&opts, "refcounted_frames", "1", 0);
if ((ret = avcodec_open2(dec_ctx, dec, &opts)) < 0) {
fprintf(stderr, "Failed to open %s codec\n", fprintf(stderr, "Failed to open %s codec\n",
av_get_media_type_string(type)); av_get_media_type_string(type));
return ret; return ret;
...@@ -187,15 +208,31 @@ int main (int argc, char **argv) ...@@ -187,15 +208,31 @@ int main (int argc, char **argv)
{ {
int ret = 0, got_frame; int ret = 0, got_frame;
if (argc != 4) { if (argc != 4 && argc != 5) {
fprintf(stderr, "usage: %s input_file video_output_file audio_output_file\n" fprintf(stderr, "usage: %s [-refcount=<old|new_norefcount|new_refcount>] "
"input_file video_output_file audio_output_file\n"
"API example program to show how to read frames from an input file.\n" "API example program to show how to read frames from an input file.\n"
"This program reads frames from a file, decodes them, and writes decoded\n" "This program reads frames from a file, decodes them, and writes decoded\n"
"video frames to a rawvideo file named video_output_file, and decoded\n" "video frames to a rawvideo file named video_output_file, and decoded\n"
"audio frames to a rawaudio file named audio_output_file.\n" "audio frames to a rawaudio file named audio_output_file.\n\n"
"If the -refcount option is specified, the program use the\n"
"reference counting frame system which allows keeping a copy of\n"
"the data for longer than one decode call. If unset, it's using\n"
"the classic old method.\n"
"\n", argv[0]); "\n", argv[0]);
exit(1); exit(1);
} }
if (argc == 5) {
const char *mode = argv[1] + strlen("-refcount=");
if (!strcmp(mode, "old")) api_mode = API_MODE_OLD;
else if (!strcmp(mode, "new_norefcount")) api_mode = API_MODE_NEW_API_NO_REF_COUNT;
else if (!strcmp(mode, "new_refcount")) api_mode = API_MODE_NEW_API_REF_COUNT;
else {
fprintf(stderr, "unknow mode '%s'\n", mode);
exit(1);
}
argv++;
}
src_filename = argv[1]; src_filename = argv[1];
video_dst_filename = argv[2]; video_dst_filename = argv[2];
audio_dst_filename = argv[3]; audio_dst_filename = argv[3];
...@@ -257,7 +294,12 @@ int main (int argc, char **argv) ...@@ -257,7 +294,12 @@ int main (int argc, char **argv)
goto end; goto end;
} }
frame = avcodec_alloc_frame(); /* When using the new API, you need to use the libavutil/frame.h API, while
* the classic frame management is available in libavcodec */
if (api_mode == API_MODE_OLD)
frame = avcodec_alloc_frame();
else
frame = av_frame_alloc();
if (!frame) { if (!frame) {
fprintf(stderr, "Could not allocate frame\n"); fprintf(stderr, "Could not allocate frame\n");
ret = AVERROR(ENOMEM); ret = AVERROR(ENOMEM);
...@@ -336,7 +378,10 @@ end: ...@@ -336,7 +378,10 @@ end:
fclose(video_dst_file); fclose(video_dst_file);
if (audio_dst_file) if (audio_dst_file)
fclose(audio_dst_file); fclose(audio_dst_file);
av_free(frame); if (api_mode == API_MODE_OLD)
avcodec_free_frame(&frame);
else
av_frame_free(&frame);
av_free(video_dst_data[0]); av_free(video_dst_data[0]);
return ret < 0; return ret < 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment