blob: c2f3c5404a9a740685ea645ea91b28dfc7ecf492 [file] [log] [blame]
Dmitry Kovalev50fa5852014-01-07 15:15:25 -08001/*
Yaowu Xu9c01aa12016-09-01 14:32:49 -07002 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Dmitry Kovalev50fa5852014-01-07 15:15:25 -08003 *
Yaowu Xu9c01aa12016-09-01 14:32:49 -07004 * This source code is subject to the terms of the BSD 2 Clause License and
5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 * was not distributed with this source code in the LICENSE file, you can
7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 * Media Patent License 1.0 was not distributed with this source code in the
9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
Dmitry Kovalev50fa5852014-01-07 15:15:25 -080010 */
11
12// Decode With Drops Example
13// =========================
14//
15// This is an example utility which drops a series of frames, as specified
16// on the command line. This is useful for observing the error recovery
17// features of the codec.
18//
19// Usage
20// -----
21// This example adds a single argument to the `simple_decoder` example,
22// which specifies the range or pattern of frames to drop. The parameter is
23// parsed as follows:
24//
25// Dropping A Range Of Frames
26// --------------------------
27// To drop a range of frames, specify the starting frame and the ending
28// frame to drop, separated by a dash. The following command will drop
29// frames 5 through 10 (base 1).
30//
31// $ ./decode_with_drops in.ivf out.i420 5-10
32//
33//
34// Dropping A Pattern Of Frames
35// ----------------------------
36// To drop a pattern of frames, specify the number of frames to drop and
37// the number of frames after which to repeat the pattern, separated by
38// a forward-slash. The following command will drop 3 of 7 frames.
39// Specifically, it will decode 4 frames, then drop 3 frames, and then
40// repeat.
41//
42// $ ./decode_with_drops in.ivf out.i420 3/7
43//
44//
45// Extra Variables
46// ---------------
47// This example maintains the pattern passed on the command line in the
48// `n`, `m`, and `is_range` variables:
49//
50//
51// Making The Drop Decision
52// ------------------------
53// The example decides whether to drop the frame based on the current
54// frame number, immediately before decoding the frame.
55
Dmitry Kovalev50fa5852014-01-07 15:15:25 -080056#include <stdio.h>
57#include <stdlib.h>
58#include <string.h>
Dmitry Kovalev834f2fb2014-01-28 11:25:24 -080059
Yaowu Xuf883b422016-08-30 14:01:10 -070060#include "aom/aomdx.h"
61#include "aom/aom_decoder.h"
Dmitry Kovalev50fa5852014-01-07 15:15:25 -080062
Tom Finegan9e96bdc2015-02-04 16:11:57 -080063#include "../tools_common.h"
64#include "../video_reader.h"
Yaowu Xuf883b422016-08-30 14:01:10 -070065#include "./aom_config.h"
Dmitry Kovalev50fa5852014-01-07 15:15:25 -080066
Dmitry Kovalev834f2fb2014-01-28 11:25:24 -080067static const char *exec_name;
Dmitry Kovalev50fa5852014-01-07 15:15:25 -080068
James Zern59e7a472015-05-09 10:33:26 -070069void usage_exit(void) {
Dmitry Kovalev834f2fb2014-01-28 11:25:24 -080070 fprintf(stderr, "Usage: %s <infile> <outfile> <N-M|N/M>\n", exec_name);
71 exit(EXIT_FAILURE);
Dmitry Kovalev50fa5852014-01-07 15:15:25 -080072}
73
Dmitry Kovalev50fa5852014-01-07 15:15:25 -080074int main(int argc, char **argv) {
Dmitry Kovalev37e6fd32014-02-05 18:34:46 -080075 int frame_cnt = 0;
76 FILE *outfile = NULL;
Yaowu Xuf883b422016-08-30 14:01:10 -070077 aom_codec_ctx_t codec;
78 const AvxInterface *decoder = NULL;
79 AvxVideoReader *reader = NULL;
80 const AvxVideoInfo *info = NULL;
Dmitry Kovalev37e6fd32014-02-05 18:34:46 -080081 int n = 0;
82 int m = 0;
83 int is_range = 0;
84 char *nptr = NULL;
Dmitry Kovalev50fa5852014-01-07 15:15:25 -080085
Dmitry Kovalev834f2fb2014-01-28 11:25:24 -080086 exec_name = argv[0];
87
clang-format397d9642016-08-08 18:51:16 -070088 if (argc != 4) die("Invalid number of arguments.");
Dmitry Kovalev834f2fb2014-01-28 11:25:24 -080089
Yaowu Xuf883b422016-08-30 14:01:10 -070090 reader = aom_video_reader_open(argv[1]);
clang-format397d9642016-08-08 18:51:16 -070091 if (!reader) die("Failed to open %s for reading.", argv[1]);
Dmitry Kovalev834f2fb2014-01-28 11:25:24 -080092
93 if (!(outfile = fopen(argv[2], "wb")))
Dmitry Kovalev37e6fd32014-02-05 18:34:46 -080094 die("Failed to open %s for writing.", argv[2]);
Dmitry Kovalev834f2fb2014-01-28 11:25:24 -080095
James Zern097fef92017-03-23 00:25:55 -070096 n = (int)strtol(argv[3], &nptr, 0);
97 m = (int)strtol(nptr + 1, NULL, 0);
Dmitry Kovalev834f2fb2014-01-28 11:25:24 -080098 is_range = (*nptr == '-');
99 if (!n || !m || (*nptr != '-' && *nptr != '/'))
Dmitry Kovalev37e6fd32014-02-05 18:34:46 -0800100 die("Couldn't parse pattern %s.\n", argv[3]);
Dmitry Kovalev834f2fb2014-01-28 11:25:24 -0800101
Yaowu Xuf883b422016-08-30 14:01:10 -0700102 info = aom_video_reader_get_info(reader);
Dmitry Kovalev834f2fb2014-01-28 11:25:24 -0800103
Yaowu Xuf883b422016-08-30 14:01:10 -0700104 decoder = get_aom_decoder_by_fourcc(info->codec_fourcc);
clang-format397d9642016-08-08 18:51:16 -0700105 if (!decoder) die("Unknown input codec.");
Dmitry Kovalev834f2fb2014-01-28 11:25:24 -0800106
Yaowu Xuf883b422016-08-30 14:01:10 -0700107 printf("Using %s\n", aom_codec_iface_name(decoder->codec_interface()));
Dmitry Kovalev834f2fb2014-01-28 11:25:24 -0800108
Yaowu Xuf883b422016-08-30 14:01:10 -0700109 if (aom_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0))
Dmitry Kovalev37e6fd32014-02-05 18:34:46 -0800110 die_codec(&codec, "Failed to initialize decoder.");
Dmitry Kovalev834f2fb2014-01-28 11:25:24 -0800111
Yaowu Xuf883b422016-08-30 14:01:10 -0700112 while (aom_video_reader_read_frame(reader)) {
113 aom_codec_iter_t iter = NULL;
114 aom_image_t *img = NULL;
Dmitry Kovalev834f2fb2014-01-28 11:25:24 -0800115 size_t frame_size = 0;
116 int skip;
clang-format397d9642016-08-08 18:51:16 -0700117 const unsigned char *frame =
Yaowu Xuf883b422016-08-30 14:01:10 -0700118 aom_video_reader_get_frame(reader, &frame_size);
Sean DuBois47cc2552018-01-23 07:44:16 +0000119 if (aom_codec_decode(&codec, frame, (unsigned int)frame_size, NULL))
Dmitry Kovalev37e6fd32014-02-05 18:34:46 -0800120 die_codec(&codec, "Failed to decode frame.");
Dmitry Kovalev834f2fb2014-01-28 11:25:24 -0800121
122 ++frame_cnt;
123
124 skip = (is_range && frame_cnt >= n && frame_cnt <= m) ||
125 (!is_range && m - (frame_cnt - 1) % m <= n);
126
127 if (!skip) {
128 putc('.', stdout);
129
Yaowu Xuf883b422016-08-30 14:01:10 -0700130 while ((img = aom_codec_get_frame(&codec, &iter)) != NULL)
131 aom_img_write(img, outfile);
Dmitry Kovalev834f2fb2014-01-28 11:25:24 -0800132 } else {
133 putc('X', stdout);
Dmitry Kovalev50fa5852014-01-07 15:15:25 -0800134 }
Dmitry Kovalev50fa5852014-01-07 15:15:25 -0800135
Dmitry Kovalev834f2fb2014-01-28 11:25:24 -0800136 fflush(stdout);
137 }
Dmitry Kovalev50fa5852014-01-07 15:15:25 -0800138
Dmitry Kovalev834f2fb2014-01-28 11:25:24 -0800139 printf("Processed %d frames.\n", frame_cnt);
Yaowu Xuf883b422016-08-30 14:01:10 -0700140 if (aom_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec.");
Dmitry Kovalev50fa5852014-01-07 15:15:25 -0800141
Dmitry Kovalev834f2fb2014-01-28 11:25:24 -0800142 printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n",
Dmitry Kovalev37e6fd32014-02-05 18:34:46 -0800143 info->frame_width, info->frame_height, argv[2]);
Dmitry Kovalev50fa5852014-01-07 15:15:25 -0800144
Yaowu Xuf883b422016-08-30 14:01:10 -0700145 aom_video_reader_close(reader);
Dmitry Kovalev834f2fb2014-01-28 11:25:24 -0800146 fclose(outfile);
Dmitry Kovalev50fa5852014-01-07 15:15:25 -0800147
Dmitry Kovalev834f2fb2014-01-28 11:25:24 -0800148 return EXIT_SUCCESS;
Dmitry Kovalev50fa5852014-01-07 15:15:25 -0800149}