Dmitry Kovalev | 50fa585 | 2014-01-07 15:15:25 -0800 | [diff] [blame] | 1 | /* |
Yaowu Xu | 9c01aa1 | 2016-09-01 14:32:49 -0700 | [diff] [blame] | 2 | * Copyright (c) 2016, Alliance for Open Media. All rights reserved |
Dmitry Kovalev | 50fa585 | 2014-01-07 15:15:25 -0800 | [diff] [blame] | 3 | * |
Yaowu Xu | 9c01aa1 | 2016-09-01 14:32:49 -0700 | [diff] [blame] | 4 | * 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 Kovalev | 50fa585 | 2014-01-07 15:15:25 -0800 | [diff] [blame] | 10 | */ |
| 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 Kovalev | 50fa585 | 2014-01-07 15:15:25 -0800 | [diff] [blame] | 56 | #include <stdio.h> |
| 57 | #include <stdlib.h> |
| 58 | #include <string.h> |
Dmitry Kovalev | 834f2fb | 2014-01-28 11:25:24 -0800 | [diff] [blame] | 59 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 60 | #include "aom/aomdx.h" |
| 61 | #include "aom/aom_decoder.h" |
Dmitry Kovalev | 50fa585 | 2014-01-07 15:15:25 -0800 | [diff] [blame] | 62 | |
Tom Finegan | 9e96bdc | 2015-02-04 16:11:57 -0800 | [diff] [blame] | 63 | #include "../tools_common.h" |
| 64 | #include "../video_reader.h" |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 65 | #include "./aom_config.h" |
Dmitry Kovalev | 50fa585 | 2014-01-07 15:15:25 -0800 | [diff] [blame] | 66 | |
Dmitry Kovalev | 834f2fb | 2014-01-28 11:25:24 -0800 | [diff] [blame] | 67 | static const char *exec_name; |
Dmitry Kovalev | 50fa585 | 2014-01-07 15:15:25 -0800 | [diff] [blame] | 68 | |
James Zern | 59e7a47 | 2015-05-09 10:33:26 -0700 | [diff] [blame] | 69 | void usage_exit(void) { |
Dmitry Kovalev | 834f2fb | 2014-01-28 11:25:24 -0800 | [diff] [blame] | 70 | fprintf(stderr, "Usage: %s <infile> <outfile> <N-M|N/M>\n", exec_name); |
| 71 | exit(EXIT_FAILURE); |
Dmitry Kovalev | 50fa585 | 2014-01-07 15:15:25 -0800 | [diff] [blame] | 72 | } |
| 73 | |
Dmitry Kovalev | 50fa585 | 2014-01-07 15:15:25 -0800 | [diff] [blame] | 74 | int main(int argc, char **argv) { |
Dmitry Kovalev | 37e6fd3 | 2014-02-05 18:34:46 -0800 | [diff] [blame] | 75 | int frame_cnt = 0; |
| 76 | FILE *outfile = NULL; |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 77 | aom_codec_ctx_t codec; |
| 78 | const AvxInterface *decoder = NULL; |
| 79 | AvxVideoReader *reader = NULL; |
| 80 | const AvxVideoInfo *info = NULL; |
Dmitry Kovalev | 37e6fd3 | 2014-02-05 18:34:46 -0800 | [diff] [blame] | 81 | int n = 0; |
| 82 | int m = 0; |
| 83 | int is_range = 0; |
| 84 | char *nptr = NULL; |
Dmitry Kovalev | 50fa585 | 2014-01-07 15:15:25 -0800 | [diff] [blame] | 85 | |
Dmitry Kovalev | 834f2fb | 2014-01-28 11:25:24 -0800 | [diff] [blame] | 86 | exec_name = argv[0]; |
| 87 | |
clang-format | 397d964 | 2016-08-08 18:51:16 -0700 | [diff] [blame] | 88 | if (argc != 4) die("Invalid number of arguments."); |
Dmitry Kovalev | 834f2fb | 2014-01-28 11:25:24 -0800 | [diff] [blame] | 89 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 90 | reader = aom_video_reader_open(argv[1]); |
clang-format | 397d964 | 2016-08-08 18:51:16 -0700 | [diff] [blame] | 91 | if (!reader) die("Failed to open %s for reading.", argv[1]); |
Dmitry Kovalev | 834f2fb | 2014-01-28 11:25:24 -0800 | [diff] [blame] | 92 | |
| 93 | if (!(outfile = fopen(argv[2], "wb"))) |
Dmitry Kovalev | 37e6fd3 | 2014-02-05 18:34:46 -0800 | [diff] [blame] | 94 | die("Failed to open %s for writing.", argv[2]); |
Dmitry Kovalev | 834f2fb | 2014-01-28 11:25:24 -0800 | [diff] [blame] | 95 | |
James Zern | 097fef9 | 2017-03-23 00:25:55 -0700 | [diff] [blame] | 96 | n = (int)strtol(argv[3], &nptr, 0); |
| 97 | m = (int)strtol(nptr + 1, NULL, 0); |
Dmitry Kovalev | 834f2fb | 2014-01-28 11:25:24 -0800 | [diff] [blame] | 98 | is_range = (*nptr == '-'); |
| 99 | if (!n || !m || (*nptr != '-' && *nptr != '/')) |
Dmitry Kovalev | 37e6fd3 | 2014-02-05 18:34:46 -0800 | [diff] [blame] | 100 | die("Couldn't parse pattern %s.\n", argv[3]); |
Dmitry Kovalev | 834f2fb | 2014-01-28 11:25:24 -0800 | [diff] [blame] | 101 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 102 | info = aom_video_reader_get_info(reader); |
Dmitry Kovalev | 834f2fb | 2014-01-28 11:25:24 -0800 | [diff] [blame] | 103 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 104 | decoder = get_aom_decoder_by_fourcc(info->codec_fourcc); |
clang-format | 397d964 | 2016-08-08 18:51:16 -0700 | [diff] [blame] | 105 | if (!decoder) die("Unknown input codec."); |
Dmitry Kovalev | 834f2fb | 2014-01-28 11:25:24 -0800 | [diff] [blame] | 106 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 107 | printf("Using %s\n", aom_codec_iface_name(decoder->codec_interface())); |
Dmitry Kovalev | 834f2fb | 2014-01-28 11:25:24 -0800 | [diff] [blame] | 108 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 109 | if (aom_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0)) |
Dmitry Kovalev | 37e6fd3 | 2014-02-05 18:34:46 -0800 | [diff] [blame] | 110 | die_codec(&codec, "Failed to initialize decoder."); |
Dmitry Kovalev | 834f2fb | 2014-01-28 11:25:24 -0800 | [diff] [blame] | 111 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 112 | while (aom_video_reader_read_frame(reader)) { |
| 113 | aom_codec_iter_t iter = NULL; |
| 114 | aom_image_t *img = NULL; |
Dmitry Kovalev | 834f2fb | 2014-01-28 11:25:24 -0800 | [diff] [blame] | 115 | size_t frame_size = 0; |
| 116 | int skip; |
clang-format | 397d964 | 2016-08-08 18:51:16 -0700 | [diff] [blame] | 117 | const unsigned char *frame = |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 118 | aom_video_reader_get_frame(reader, &frame_size); |
Sean DuBois | 47cc255 | 2018-01-23 07:44:16 +0000 | [diff] [blame] | 119 | if (aom_codec_decode(&codec, frame, (unsigned int)frame_size, NULL)) |
Dmitry Kovalev | 37e6fd3 | 2014-02-05 18:34:46 -0800 | [diff] [blame] | 120 | die_codec(&codec, "Failed to decode frame."); |
Dmitry Kovalev | 834f2fb | 2014-01-28 11:25:24 -0800 | [diff] [blame] | 121 | |
| 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 Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 130 | while ((img = aom_codec_get_frame(&codec, &iter)) != NULL) |
| 131 | aom_img_write(img, outfile); |
Dmitry Kovalev | 834f2fb | 2014-01-28 11:25:24 -0800 | [diff] [blame] | 132 | } else { |
| 133 | putc('X', stdout); |
Dmitry Kovalev | 50fa585 | 2014-01-07 15:15:25 -0800 | [diff] [blame] | 134 | } |
Dmitry Kovalev | 50fa585 | 2014-01-07 15:15:25 -0800 | [diff] [blame] | 135 | |
Dmitry Kovalev | 834f2fb | 2014-01-28 11:25:24 -0800 | [diff] [blame] | 136 | fflush(stdout); |
| 137 | } |
Dmitry Kovalev | 50fa585 | 2014-01-07 15:15:25 -0800 | [diff] [blame] | 138 | |
Dmitry Kovalev | 834f2fb | 2014-01-28 11:25:24 -0800 | [diff] [blame] | 139 | printf("Processed %d frames.\n", frame_cnt); |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 140 | if (aom_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec."); |
Dmitry Kovalev | 50fa585 | 2014-01-07 15:15:25 -0800 | [diff] [blame] | 141 | |
Dmitry Kovalev | 834f2fb | 2014-01-28 11:25:24 -0800 | [diff] [blame] | 142 | printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n", |
Dmitry Kovalev | 37e6fd3 | 2014-02-05 18:34:46 -0800 | [diff] [blame] | 143 | info->frame_width, info->frame_height, argv[2]); |
Dmitry Kovalev | 50fa585 | 2014-01-07 15:15:25 -0800 | [diff] [blame] | 144 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 145 | aom_video_reader_close(reader); |
Dmitry Kovalev | 834f2fb | 2014-01-28 11:25:24 -0800 | [diff] [blame] | 146 | fclose(outfile); |
Dmitry Kovalev | 50fa585 | 2014-01-07 15:15:25 -0800 | [diff] [blame] | 147 | |
Dmitry Kovalev | 834f2fb | 2014-01-28 11:25:24 -0800 | [diff] [blame] | 148 | return EXIT_SUCCESS; |
Dmitry Kovalev | 50fa585 | 2014-01-07 15:15:25 -0800 | [diff] [blame] | 149 | } |