doc/examples/demuxing: show how to use the reference counting system.
This commit is contained in:
parent
405ceb1812
commit
d10b1a200d
@ -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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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:
|
|||||||
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;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user