|
|
|
@ -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; |
|
|
|
|