Imported Debian version 2.4.3~trusty1
[deb_ffmpeg.git] / ffmpeg / doc / examples / demuxing_decoding.c
CommitLineData
2ba45a60
DM
1/*
2 * Copyright (c) 2012 Stefano Sabatini
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23/**
24 * @file
25 * Demuxing and decoding example.
26 *
27 * Show how to use the libavformat and libavcodec API to demux and
28 * decode audio and video data.
29 * @example demuxing_decoding.c
30 */
31
32#include <libavutil/imgutils.h>
33#include <libavutil/samplefmt.h>
34#include <libavutil/timestamp.h>
35#include <libavformat/avformat.h>
36
37static AVFormatContext *fmt_ctx = NULL;
38static AVCodecContext *video_dec_ctx = NULL, *audio_dec_ctx;
39static AVStream *video_stream = NULL, *audio_stream = NULL;
40static const char *src_filename = NULL;
41static const char *video_dst_filename = NULL;
42static const char *audio_dst_filename = NULL;
43static FILE *video_dst_file = NULL;
44static FILE *audio_dst_file = NULL;
45
46static uint8_t *video_dst_data[4] = {NULL};
47static int video_dst_linesize[4];
48static int video_dst_bufsize;
49
50static int video_stream_idx = -1, audio_stream_idx = -1;
51static AVFrame *frame = NULL;
52static AVPacket pkt;
53static int video_frame_count = 0;
54static int audio_frame_count = 0;
55
56/* The different ways of decoding and managing data memory. You are not
57 * supposed to support all the modes in your application but pick the one most
58 * appropriate to your needs. Look for the use of api_mode in this example to
59 * see what are the differences of API usage between them */
60enum {
61 API_MODE_OLD = 0, /* old method, deprecated */
62 API_MODE_NEW_API_REF_COUNT = 1, /* new method, using the frame reference counting */
63 API_MODE_NEW_API_NO_REF_COUNT = 2, /* new method, without reference counting */
64};
65
66static int api_mode = API_MODE_OLD;
67
68static int decode_packet(int *got_frame, int cached)
69{
70 int ret = 0;
71 int decoded = pkt.size;
72
73 *got_frame = 0;
74
75 if (pkt.stream_index == video_stream_idx) {
76 /* decode video frame */
77 ret = avcodec_decode_video2(video_dec_ctx, frame, got_frame, &pkt);
78 if (ret < 0) {
79 fprintf(stderr, "Error decoding video frame (%s)\n", av_err2str(ret));
80 return ret;
81 }
82
83 if (*got_frame) {
84 printf("video_frame%s n:%d coded_n:%d pts:%s\n",
85 cached ? "(cached)" : "",
86 video_frame_count++, frame->coded_picture_number,
87 av_ts2timestr(frame->pts, &video_dec_ctx->time_base));
88
89 /* copy decoded frame to destination buffer:
90 * this is required since rawvideo expects non aligned data */
91 av_image_copy(video_dst_data, video_dst_linesize,
92 (const uint8_t **)(frame->data), frame->linesize,
93 video_dec_ctx->pix_fmt, video_dec_ctx->width, video_dec_ctx->height);
94
95 /* write to rawvideo file */
96 fwrite(video_dst_data[0], 1, video_dst_bufsize, video_dst_file);
97 }
98 } else if (pkt.stream_index == audio_stream_idx) {
99 /* decode audio frame */
100 ret = avcodec_decode_audio4(audio_dec_ctx, frame, got_frame, &pkt);
101 if (ret < 0) {
102 fprintf(stderr, "Error decoding audio frame (%s)\n", av_err2str(ret));
103 return ret;
104 }
105 /* Some audio decoders decode only part of the packet, and have to be
106 * called again with the remainder of the packet data.
107 * Sample: fate-suite/lossless-audio/luckynight-partial.shn
108 * Also, some decoders might over-read the packet. */
109 decoded = FFMIN(ret, pkt.size);
110
111 if (*got_frame) {
112 size_t unpadded_linesize = frame->nb_samples * av_get_bytes_per_sample(frame->format);
113 printf("audio_frame%s n:%d nb_samples:%d pts:%s\n",
114 cached ? "(cached)" : "",
115 audio_frame_count++, frame->nb_samples,
116 av_ts2timestr(frame->pts, &audio_dec_ctx->time_base));
117
118 /* Write the raw audio data samples of the first plane. This works
119 * fine for packed formats (e.g. AV_SAMPLE_FMT_S16). However,
120 * most audio decoders output planar audio, which uses a separate
121 * plane of audio samples for each channel (e.g. AV_SAMPLE_FMT_S16P).
122 * In other words, this code will write only the first audio channel
123 * in these cases.
124 * You should use libswresample or libavfilter to convert the frame
125 * to packed data. */
126 fwrite(frame->extended_data[0], 1, unpadded_linesize, audio_dst_file);
127 }
128 }
129
130 /* If we use the new API with reference counting, we own the data and need
131 * to de-reference it when we don't use it anymore */
132 if (*got_frame && api_mode == API_MODE_NEW_API_REF_COUNT)
133 av_frame_unref(frame);
134
135 return decoded;
136}
137
138static int open_codec_context(int *stream_idx,
139 AVFormatContext *fmt_ctx, enum AVMediaType type)
140{
141 int ret;
142 AVStream *st;
143 AVCodecContext *dec_ctx = NULL;
144 AVCodec *dec = NULL;
145 AVDictionary *opts = NULL;
146
147 ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0);
148 if (ret < 0) {
149 fprintf(stderr, "Could not find %s stream in input file '%s'\n",
150 av_get_media_type_string(type), src_filename);
151 return ret;
152 } else {
153 *stream_idx = ret;
154 st = fmt_ctx->streams[*stream_idx];
155
156 /* find decoder for the stream */
157 dec_ctx = st->codec;
158 dec = avcodec_find_decoder(dec_ctx->codec_id);
159 if (!dec) {
160 fprintf(stderr, "Failed to find %s codec\n",
161 av_get_media_type_string(type));
162 return AVERROR(EINVAL);
163 }
164
165 /* Init the decoders, with or without reference counting */
166 if (api_mode == API_MODE_NEW_API_REF_COUNT)
167 av_dict_set(&opts, "refcounted_frames", "1", 0);
168 if ((ret = avcodec_open2(dec_ctx, dec, &opts)) < 0) {
169 fprintf(stderr, "Failed to open %s codec\n",
170 av_get_media_type_string(type));
171 return ret;
172 }
173 }
174
175 return 0;
176}
177
178static int get_format_from_sample_fmt(const char **fmt,
179 enum AVSampleFormat sample_fmt)
180{
181 int i;
182 struct sample_fmt_entry {
183 enum AVSampleFormat sample_fmt; const char *fmt_be, *fmt_le;
184 } sample_fmt_entries[] = {
185 { AV_SAMPLE_FMT_U8, "u8", "u8" },
186 { AV_SAMPLE_FMT_S16, "s16be", "s16le" },
187 { AV_SAMPLE_FMT_S32, "s32be", "s32le" },
188 { AV_SAMPLE_FMT_FLT, "f32be", "f32le" },
189 { AV_SAMPLE_FMT_DBL, "f64be", "f64le" },
190 };
191 *fmt = NULL;
192
193 for (i = 0; i < FF_ARRAY_ELEMS(sample_fmt_entries); i++) {
194 struct sample_fmt_entry *entry = &sample_fmt_entries[i];
195 if (sample_fmt == entry->sample_fmt) {
196 *fmt = AV_NE(entry->fmt_be, entry->fmt_le);
197 return 0;
198 }
199 }
200
201 fprintf(stderr,
202 "sample format %s is not supported as output format\n",
203 av_get_sample_fmt_name(sample_fmt));
204 return -1;
205}
206
207int main (int argc, char **argv)
208{
209 int ret = 0, got_frame;
210
211 if (argc != 4 && argc != 5) {
212 fprintf(stderr, "usage: %s [-refcount=<old|new_norefcount|new_refcount>] "
213 "input_file video_output_file audio_output_file\n"
214 "API example program to show how to read frames from an input file.\n"
215 "This program reads frames from a file, decodes them, and writes decoded\n"
216 "video frames to a rawvideo file named video_output_file, and decoded\n"
217 "audio frames to a rawaudio file named audio_output_file.\n\n"
218 "If the -refcount option is specified, the program use the\n"
219 "reference counting frame system which allows keeping a copy of\n"
220 "the data for longer than one decode call. If unset, it's using\n"
221 "the classic old method.\n"
222 "\n", argv[0]);
223 exit(1);
224 }
225 if (argc == 5) {
226 const char *mode = argv[1] + strlen("-refcount=");
227 if (!strcmp(mode, "old")) api_mode = API_MODE_OLD;
228 else if (!strcmp(mode, "new_norefcount")) api_mode = API_MODE_NEW_API_NO_REF_COUNT;
229 else if (!strcmp(mode, "new_refcount")) api_mode = API_MODE_NEW_API_REF_COUNT;
230 else {
231 fprintf(stderr, "unknow mode '%s'\n", mode);
232 exit(1);
233 }
234 argv++;
235 }
236 src_filename = argv[1];
237 video_dst_filename = argv[2];
238 audio_dst_filename = argv[3];
239
240 /* register all formats and codecs */
241 av_register_all();
242
243 /* open input file, and allocate format context */
244 if (avformat_open_input(&fmt_ctx, src_filename, NULL, NULL) < 0) {
245 fprintf(stderr, "Could not open source file %s\n", src_filename);
246 exit(1);
247 }
248
249 /* retrieve stream information */
250 if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
251 fprintf(stderr, "Could not find stream information\n");
252 exit(1);
253 }
254
255 if (open_codec_context(&video_stream_idx, fmt_ctx, AVMEDIA_TYPE_VIDEO) >= 0) {
256 video_stream = fmt_ctx->streams[video_stream_idx];
257 video_dec_ctx = video_stream->codec;
258
259 video_dst_file = fopen(video_dst_filename, "wb");
260 if (!video_dst_file) {
261 fprintf(stderr, "Could not open destination file %s\n", video_dst_filename);
262 ret = 1;
263 goto end;
264 }
265
266 /* allocate image where the decoded image will be put */
267 ret = av_image_alloc(video_dst_data, video_dst_linesize,
268 video_dec_ctx->width, video_dec_ctx->height,
269 video_dec_ctx->pix_fmt, 1);
270 if (ret < 0) {
271 fprintf(stderr, "Could not allocate raw video buffer\n");
272 goto end;
273 }
274 video_dst_bufsize = ret;
275 }
276
277 if (open_codec_context(&audio_stream_idx, fmt_ctx, AVMEDIA_TYPE_AUDIO) >= 0) {
278 audio_stream = fmt_ctx->streams[audio_stream_idx];
279 audio_dec_ctx = audio_stream->codec;
280 audio_dst_file = fopen(audio_dst_filename, "wb");
281 if (!audio_dst_file) {
282 fprintf(stderr, "Could not open destination file %s\n", audio_dst_filename);
283 ret = 1;
284 goto end;
285 }
286 }
287
288 /* dump input information to stderr */
289 av_dump_format(fmt_ctx, 0, src_filename, 0);
290
291 if (!audio_stream && !video_stream) {
292 fprintf(stderr, "Could not find audio or video stream in the input, aborting\n");
293 ret = 1;
294 goto end;
295 }
296
297 /* When using the new API, you need to use the libavutil/frame.h API, while
298 * the classic frame management is available in libavcodec */
299 if (api_mode == API_MODE_OLD)
300 frame = avcodec_alloc_frame();
301 else
302 frame = av_frame_alloc();
303 if (!frame) {
304 fprintf(stderr, "Could not allocate frame\n");
305 ret = AVERROR(ENOMEM);
306 goto end;
307 }
308
309 /* initialize packet, set data to NULL, let the demuxer fill it */
310 av_init_packet(&pkt);
311 pkt.data = NULL;
312 pkt.size = 0;
313
314 if (video_stream)
315 printf("Demuxing video from file '%s' into '%s'\n", src_filename, video_dst_filename);
316 if (audio_stream)
317 printf("Demuxing audio from file '%s' into '%s'\n", src_filename, audio_dst_filename);
318
319 /* read frames from the file */
320 while (av_read_frame(fmt_ctx, &pkt) >= 0) {
321 AVPacket orig_pkt = pkt;
322 do {
323 ret = decode_packet(&got_frame, 0);
324 if (ret < 0)
325 break;
326 pkt.data += ret;
327 pkt.size -= ret;
328 } while (pkt.size > 0);
329 av_free_packet(&orig_pkt);
330 }
331
332 /* flush cached frames */
333 pkt.data = NULL;
334 pkt.size = 0;
335 do {
336 decode_packet(&got_frame, 1);
337 } while (got_frame);
338
339 printf("Demuxing succeeded.\n");
340
341 if (video_stream) {
342 printf("Play the output video file with the command:\n"
343 "ffplay -f rawvideo -pix_fmt %s -video_size %dx%d %s\n",
344 av_get_pix_fmt_name(video_dec_ctx->pix_fmt), video_dec_ctx->width, video_dec_ctx->height,
345 video_dst_filename);
346 }
347
348 if (audio_stream) {
349 enum AVSampleFormat sfmt = audio_dec_ctx->sample_fmt;
350 int n_channels = audio_dec_ctx->channels;
351 const char *fmt;
352
353 if (av_sample_fmt_is_planar(sfmt)) {
354 const char *packed = av_get_sample_fmt_name(sfmt);
355 printf("Warning: the sample format the decoder produced is planar "
356 "(%s). This example will output the first channel only.\n",
357 packed ? packed : "?");
358 sfmt = av_get_packed_sample_fmt(sfmt);
359 n_channels = 1;
360 }
361
362 if ((ret = get_format_from_sample_fmt(&fmt, sfmt)) < 0)
363 goto end;
364
365 printf("Play the output audio file with the command:\n"
366 "ffplay -f %s -ac %d -ar %d %s\n",
367 fmt, n_channels, audio_dec_ctx->sample_rate,
368 audio_dst_filename);
369 }
370
371end:
372 avcodec_close(video_dec_ctx);
373 avcodec_close(audio_dec_ctx);
374 avformat_close_input(&fmt_ctx);
375 if (video_dst_file)
376 fclose(video_dst_file);
377 if (audio_dst_file)
378 fclose(audio_dst_file);
379 if (api_mode == API_MODE_OLD)
380 avcodec_free_frame(&frame);
381 else
382 av_frame_free(&frame);
383 av_free(video_dst_data[0]);
384
385 return ret < 0;
386}