[FFmpeg-cvslog] doc/examples/demuxing: show how to use the reference counting system.
Clément Bœsch
git at videolan.org
Mon Nov 4 12:54:09 CET 2013
ffmpeg | branch: master | Clément Bœsch <clement at stupeflix.com> | Wed Oct 30 15:50:36 2013 +0100| [d10b1a200dc3676f014f7e2c020800a15c7cab8a] | committer: Clément Bœsch
doc/examples/demuxing: show how to use the reference counting system.
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=d10b1a200dc3676f014f7e2c020800a15c7cab8a
---
doc/examples/demuxing.c | 57 ++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 51 insertions(+), 6 deletions(-)
diff --git a/doc/examples/demuxing.c b/doc/examples/demuxing.c
index 7ae3654..b13246e 100644
--- a/doc/examples/demuxing.c
+++ b/doc/examples/demuxing.c
@@ -53,6 +53,18 @@ static AVPacket pkt;
static int video_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)
{
int ret = 0;
@@ -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;
}
@@ -125,6 +142,7 @@ static int open_codec_context(int *stream_idx,
AVStream *st;
AVCodecContext *dec_ctx = NULL;
AVCodec *dec = NULL;
+ AVDictionary *opts = NULL;
ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0);
if (ret < 0) {
@@ -144,7 +162,10 @@ static int open_codec_context(int *stream_idx,
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",
av_get_media_type_string(type));
return ret;
@@ -187,15 +208,31 @@ int main (int argc, char **argv)
{
int ret = 0, got_frame;
- if (argc != 4) {
- fprintf(stderr, "usage: %s input_file video_output_file audio_output_file\n"
+ if (argc != 4 && argc != 5) {
+ 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"
"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"
- "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]);
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];
video_dst_filename = argv[2];
audio_dst_filename = argv[3];
@@ -257,7 +294,12 @@ int main (int argc, char **argv)
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) {
fprintf(stderr, "Could not allocate frame\n");
ret = AVERROR(ENOMEM);
@@ -336,7 +378,10 @@ end:
fclose(video_dst_file);
if (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]);
return ret < 0;
More information about the ffmpeg-cvslog
mailing list