blob: 08a21668542e98c1cc443e4d1f897b11ac4080bf [file] [log] [blame]
Dmitry Kovalev50fa5852014-01-07 15:15:25 -08001/*
2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11
12// Simple Decoder
13// ==============
14//
15// This is an example of a simple decoder loop. It takes an input file
16// containing the compressed data (in IVF format), passes it through the
17// decoder, and writes the decompressed frames to disk. Other decoder
18// examples build upon this one.
19//
20// The details of the IVF format have been elided from this example for
21// simplicity of presentation, as IVF files will not generally be used by
22// your application. In general, an IVF file consists of a file header,
23// followed by a variable number of frames. Each frame consists of a frame
24// header followed by a variable length payload. The length of the payload
25// is specified in the first four bytes of the frame header. The payload is
26// the raw compressed data.
27//
28// Standard Includes
29// -----------------
30// For decoders, you only have to include `vpx_decoder.h` and then any
31// header files for the specific codecs you use. In this case, we're using
Dmitry Kovalev9cdaa3d2014-08-15 14:32:41 -070032// vp8.
Dmitry Kovalev50fa5852014-01-07 15:15:25 -080033//
34// Initializing The Codec
35// ----------------------
Tom Fineganc9527aa2014-09-30 11:21:56 -070036// The libvpx decoder is initialized by the call to vpx_codec_dec_init().
37// Determining the codec interface to use is handled by VpxVideoReader and the
38// functions prefixed with vpx_video_reader_. Discussion of those functions is
39// beyond the scope of this example, but the main gist is to open the input file
40// and parse just enough of it to determine if it's a VPx file and which VPx
41// codec is contained within the file.
42// Note the NULL pointer passed to vpx_codec_dec_init(). We do that in this
43// example because we want the algorithm to determine the stream configuration
44// (width/height) and allocate memory automatically.
Dmitry Kovalev50fa5852014-01-07 15:15:25 -080045//
46// Decoding A Frame
47// ----------------
48// Once the frame has been read into memory, it is decoded using the
49// `vpx_codec_decode` function. The call takes a pointer to the data
Tom Fineganc9527aa2014-09-30 11:21:56 -070050// (`frame`) and the length of the data (`frame_size`). No application data
Dmitry Kovalev50fa5852014-01-07 15:15:25 -080051// is associated with the frame in this example, so the `user_priv`
52// parameter is NULL. The `deadline` parameter is left at zero for this
Tom Fineganc9527aa2014-09-30 11:21:56 -070053// example. This parameter is generally only used when doing adaptive post
54// processing.
Dmitry Kovalev50fa5852014-01-07 15:15:25 -080055//
56// Codecs may produce a variable number of output frames for every call to
57// `vpx_codec_decode`. These frames are retrieved by the
58// `vpx_codec_get_frame` iterator function. The iterator variable `iter` is
59// initialized to NULL each time `vpx_codec_decode` is called.
60// `vpx_codec_get_frame` is called in a loop, returning a pointer to a
61// decoded image or NULL to indicate the end of list.
62//
63// Processing The Decoded Data
64// ---------------------------
65// In this example, we simply write the encoded data to disk. It is
66// important to honor the image's `stride` values.
67//
68// Cleanup
69// -------
70// The `vpx_codec_destroy` call frees any memory allocated by the codec.
71//
72// Error Handling
73// --------------
74// This example does not special case any error return codes. If there was
75// an error, a descriptive message is printed and the program exits. With
Tom Fineganc9527aa2014-09-30 11:21:56 -070076// few exceptions, vpx_codec functions return an enumerated error status,
Dmitry Kovalev50fa5852014-01-07 15:15:25 -080077// with the value `0` indicating success.
78
Dmitry Kovalev50fa5852014-01-07 15:15:25 -080079#include <stdio.h>
80#include <stdlib.h>
81#include <string.h>
Dmitry Kovalev7ec27692014-01-27 13:40:29 -080082
Dmitry Kovalev50fa5852014-01-07 15:15:25 -080083#include "vpx/vpx_decoder.h"
Dmitry Kovalev50fa5852014-01-07 15:15:25 -080084
Tom Finegan9e96bdc2015-02-04 16:11:57 -080085#include "../tools_common.h"
86#include "../video_reader.h"
Dmitry Kovalev7ec27692014-01-27 13:40:29 -080087#include "./vpx_config.h"
Dmitry Kovalev50fa5852014-01-07 15:15:25 -080088
Dmitry Kovalev7ec27692014-01-27 13:40:29 -080089static const char *exec_name;
Dmitry Kovalev50fa5852014-01-07 15:15:25 -080090
Dmitry Kovalev7ec27692014-01-27 13:40:29 -080091void usage_exit() {
92 fprintf(stderr, "Usage: %s <infile> <outfile>\n", exec_name);
93 exit(EXIT_FAILURE);
Dmitry Kovalev50fa5852014-01-07 15:15:25 -080094}
95
Dmitry Kovalev50fa5852014-01-07 15:15:25 -080096int main(int argc, char **argv) {
Dmitry Kovalev37e6fd32014-02-05 18:34:46 -080097 int frame_cnt = 0;
98 FILE *outfile = NULL;
Dmitry Kovalev7ec27692014-01-27 13:40:29 -080099 vpx_codec_ctx_t codec;
Dmitry Kovalev37e6fd32014-02-05 18:34:46 -0800100 VpxVideoReader *reader = NULL;
Dmitry Kovalev70d96642014-02-11 21:12:23 -0800101 const VpxInterface *decoder = NULL;
Dmitry Kovalev37e6fd32014-02-05 18:34:46 -0800102 const VpxVideoInfo *info = NULL;
Dmitry Kovalev50fa5852014-01-07 15:15:25 -0800103
Dmitry Kovalev7ec27692014-01-27 13:40:29 -0800104 exec_name = argv[0];
Dmitry Kovalev50fa5852014-01-07 15:15:25 -0800105
Dmitry Kovalev7ec27692014-01-27 13:40:29 -0800106 if (argc != 3)
Dmitry Kovalev37e6fd32014-02-05 18:34:46 -0800107 die("Invalid number of arguments.");
Dmitry Kovalev50fa5852014-01-07 15:15:25 -0800108
Dmitry Kovalev37e6fd32014-02-05 18:34:46 -0800109 reader = vpx_video_reader_open(argv[1]);
110 if (!reader)
111 die("Failed to open %s for reading.", argv[1]);
Dmitry Kovalev50fa5852014-01-07 15:15:25 -0800112
Dmitry Kovalev7ec27692014-01-27 13:40:29 -0800113 if (!(outfile = fopen(argv[2], "wb")))
Dmitry Kovalev37e6fd32014-02-05 18:34:46 -0800114 die("Failed to open %s for writing.", argv[2]);
Dmitry Kovalev50fa5852014-01-07 15:15:25 -0800115
Dmitry Kovalev37e6fd32014-02-05 18:34:46 -0800116 info = vpx_video_reader_get_info(reader);
Dmitry Kovalev50fa5852014-01-07 15:15:25 -0800117
Dmitry Kovalev70d96642014-02-11 21:12:23 -0800118 decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
119 if (!decoder)
Dmitry Kovalev37e6fd32014-02-05 18:34:46 -0800120 die("Unknown input codec.");
Dmitry Kovalev50fa5852014-01-07 15:15:25 -0800121
Deb Mukherjeef332c632014-07-15 16:55:12 -0700122 printf("Using %s\n", vpx_codec_iface_name(decoder->codec_interface()));
Dmitry Kovalev50fa5852014-01-07 15:15:25 -0800123
Deb Mukherjeef332c632014-07-15 16:55:12 -0700124 if (vpx_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0))
Dmitry Kovalev37e6fd32014-02-05 18:34:46 -0800125 die_codec(&codec, "Failed to initialize decoder.");
Dmitry Kovalev50fa5852014-01-07 15:15:25 -0800126
Dmitry Kovalev37e6fd32014-02-05 18:34:46 -0800127 while (vpx_video_reader_read_frame(reader)) {
Dmitry Kovalev7ec27692014-01-27 13:40:29 -0800128 vpx_codec_iter_t iter = NULL;
129 vpx_image_t *img = NULL;
130 size_t frame_size = 0;
Dmitry Kovalev37e6fd32014-02-05 18:34:46 -0800131 const unsigned char *frame = vpx_video_reader_get_frame(reader,
132 &frame_size);
Tom Fineganebf45502014-02-19 12:08:18 -0800133 if (vpx_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0))
Dmitry Kovalev37e6fd32014-02-05 18:34:46 -0800134 die_codec(&codec, "Failed to decode frame.");
Dmitry Kovalev50fa5852014-01-07 15:15:25 -0800135
Dmitry Kovalev7ec27692014-01-27 13:40:29 -0800136 while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL) {
137 vpx_img_write(img, outfile);
138 ++frame_cnt;
Dmitry Kovalev50fa5852014-01-07 15:15:25 -0800139 }
Dmitry Kovalev7ec27692014-01-27 13:40:29 -0800140 }
Dmitry Kovalev50fa5852014-01-07 15:15:25 -0800141
Dmitry Kovalev7ec27692014-01-27 13:40:29 -0800142 printf("Processed %d frames.\n", frame_cnt);
143 if (vpx_codec_destroy(&codec))
144 die_codec(&codec, "Failed to destroy codec");
145
146 printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n",
Dmitry Kovalev37e6fd32014-02-05 18:34:46 -0800147 info->frame_width, info->frame_height, argv[2]);
Dmitry Kovalev7ec27692014-01-27 13:40:29 -0800148
Dmitry Kovalev37e6fd32014-02-05 18:34:46 -0800149 vpx_video_reader_close(reader);
Dmitry Kovalev7ec27692014-01-27 13:40:29 -0800150
151 fclose(outfile);
Dmitry Kovalev7ec27692014-01-27 13:40:29 -0800152
153 return EXIT_SUCCESS;
Dmitry Kovalev50fa5852014-01-07 15:15:25 -0800154}