1233d2500723e5594f3e7c70896ffeeef32b9c950ywan/*
2233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3233d2500723e5594f3e7c70896ffeeef32b9c950ywan *
4233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  Use of this source code is governed by a BSD-style license
5233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  that can be found in the LICENSE file in the root of the source
6233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  tree. An additional intellectual property rights grant can be found
7233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  in the file PATENTS.  All contributing project authors may
8233d2500723e5594f3e7c70896ffeeef32b9c950ywan *  be found in the AUTHORS file in the root of the source tree.
9233d2500723e5594f3e7c70896ffeeef32b9c950ywan */
10233d2500723e5594f3e7c70896ffeeef32b9c950ywan
11233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Decode With Drops Example
12233d2500723e5594f3e7c70896ffeeef32b9c950ywan// =========================
13233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
14233d2500723e5594f3e7c70896ffeeef32b9c950ywan// This is an example utility which drops a series of frames, as specified
15233d2500723e5594f3e7c70896ffeeef32b9c950ywan// on the command line. This is useful for observing the error recovery
16233d2500723e5594f3e7c70896ffeeef32b9c950ywan// features of the codec.
17233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
18233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Usage
19233d2500723e5594f3e7c70896ffeeef32b9c950ywan// -----
20233d2500723e5594f3e7c70896ffeeef32b9c950ywan// This example adds a single argument to the `simple_decoder` example,
21233d2500723e5594f3e7c70896ffeeef32b9c950ywan// which specifies the range or pattern of frames to drop. The parameter is
22233d2500723e5594f3e7c70896ffeeef32b9c950ywan// parsed as follows:
23233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
24233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Dropping A Range Of Frames
25233d2500723e5594f3e7c70896ffeeef32b9c950ywan// --------------------------
26233d2500723e5594f3e7c70896ffeeef32b9c950ywan// To drop a range of frames, specify the starting frame and the ending
27233d2500723e5594f3e7c70896ffeeef32b9c950ywan// frame to drop, separated by a dash. The following command will drop
28233d2500723e5594f3e7c70896ffeeef32b9c950ywan// frames 5 through 10 (base 1).
29233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
30233d2500723e5594f3e7c70896ffeeef32b9c950ywan//  $ ./decode_with_drops in.ivf out.i420 5-10
31233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
32233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
33233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Dropping A Pattern Of Frames
34233d2500723e5594f3e7c70896ffeeef32b9c950ywan// ----------------------------
35233d2500723e5594f3e7c70896ffeeef32b9c950ywan// To drop a pattern of frames, specify the number of frames to drop and
36233d2500723e5594f3e7c70896ffeeef32b9c950ywan// the number of frames after which to repeat the pattern, separated by
37233d2500723e5594f3e7c70896ffeeef32b9c950ywan// a forward-slash. The following command will drop 3 of 7 frames.
38233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Specifically, it will decode 4 frames, then drop 3 frames, and then
39233d2500723e5594f3e7c70896ffeeef32b9c950ywan// repeat.
40233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
41233d2500723e5594f3e7c70896ffeeef32b9c950ywan//  $ ./decode_with_drops in.ivf out.i420 3/7
42233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
43233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
44233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Extra Variables
45233d2500723e5594f3e7c70896ffeeef32b9c950ywan// ---------------
46233d2500723e5594f3e7c70896ffeeef32b9c950ywan// This example maintains the pattern passed on the command line in the
47233d2500723e5594f3e7c70896ffeeef32b9c950ywan// `n`, `m`, and `is_range` variables:
48233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
49233d2500723e5594f3e7c70896ffeeef32b9c950ywan//
50233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Making The Drop Decision
51233d2500723e5594f3e7c70896ffeeef32b9c950ywan// ------------------------
52233d2500723e5594f3e7c70896ffeeef32b9c950ywan// The example decides whether to drop the frame based on the current
53233d2500723e5594f3e7c70896ffeeef32b9c950ywan// frame number, immediately before decoding the frame.
54233d2500723e5594f3e7c70896ffeeef32b9c950ywan
55233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <stdio.h>
56233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <stdlib.h>
57233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <string.h>
58233d2500723e5594f3e7c70896ffeeef32b9c950ywan
59233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define VPX_CODEC_DISABLE_COMPAT 1
60233d2500723e5594f3e7c70896ffeeef32b9c950ywan
61233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx/vp8dx.h"
62233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx/vpx_decoder.h"
63233d2500723e5594f3e7c70896ffeeef32b9c950ywan
64233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./tools_common.h"
65233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./video_reader.h"
66233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./vpx_config.h"
67233d2500723e5594f3e7c70896ffeeef32b9c950ywan
68233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic const char *exec_name;
69233d2500723e5594f3e7c70896ffeeef32b9c950ywan
70233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid usage_exit() {
71233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fprintf(stderr, "Usage: %s <infile> <outfile> <N-M|N/M>\n", exec_name);
72233d2500723e5594f3e7c70896ffeeef32b9c950ywan  exit(EXIT_FAILURE);
73233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
74233d2500723e5594f3e7c70896ffeeef32b9c950ywan
75233d2500723e5594f3e7c70896ffeeef32b9c950ywanint main(int argc, char **argv) {
76233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int frame_cnt = 0;
77233d2500723e5594f3e7c70896ffeeef32b9c950ywan  FILE *outfile = NULL;
78233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_codec_ctx_t codec;
79233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const VpxInterface *decoder = NULL;
80233d2500723e5594f3e7c70896ffeeef32b9c950ywan  VpxVideoReader *reader = NULL;
81233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const VpxVideoInfo *info = NULL;
82233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int n = 0;
83233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int m = 0;
84233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int is_range = 0;
85233d2500723e5594f3e7c70896ffeeef32b9c950ywan  char *nptr = NULL;
86233d2500723e5594f3e7c70896ffeeef32b9c950ywan
87233d2500723e5594f3e7c70896ffeeef32b9c950ywan  exec_name = argv[0];
88233d2500723e5594f3e7c70896ffeeef32b9c950ywan
89233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (argc != 4)
90233d2500723e5594f3e7c70896ffeeef32b9c950ywan    die("Invalid number of arguments.");
91233d2500723e5594f3e7c70896ffeeef32b9c950ywan
92233d2500723e5594f3e7c70896ffeeef32b9c950ywan  reader = vpx_video_reader_open(argv[1]);
93233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!reader)
94233d2500723e5594f3e7c70896ffeeef32b9c950ywan    die("Failed to open %s for reading.", argv[1]);
95233d2500723e5594f3e7c70896ffeeef32b9c950ywan
96233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!(outfile = fopen(argv[2], "wb")))
97233d2500723e5594f3e7c70896ffeeef32b9c950ywan    die("Failed to open %s for writing.", argv[2]);
98233d2500723e5594f3e7c70896ffeeef32b9c950ywan
99233d2500723e5594f3e7c70896ffeeef32b9c950ywan  n = strtol(argv[3], &nptr, 0);
100233d2500723e5594f3e7c70896ffeeef32b9c950ywan  m = strtol(nptr + 1, NULL, 0);
101233d2500723e5594f3e7c70896ffeeef32b9c950ywan  is_range = (*nptr == '-');
102233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!n || !m || (*nptr != '-' && *nptr != '/'))
103233d2500723e5594f3e7c70896ffeeef32b9c950ywan    die("Couldn't parse pattern %s.\n", argv[3]);
104233d2500723e5594f3e7c70896ffeeef32b9c950ywan
105233d2500723e5594f3e7c70896ffeeef32b9c950ywan  info = vpx_video_reader_get_info(reader);
106233d2500723e5594f3e7c70896ffeeef32b9c950ywan
107233d2500723e5594f3e7c70896ffeeef32b9c950ywan  decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
108233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!decoder)
109233d2500723e5594f3e7c70896ffeeef32b9c950ywan    die("Unknown input codec.");
110233d2500723e5594f3e7c70896ffeeef32b9c950ywan
111233d2500723e5594f3e7c70896ffeeef32b9c950ywan  printf("Using %s\n", vpx_codec_iface_name(decoder->interface()));
112233d2500723e5594f3e7c70896ffeeef32b9c950ywan
113233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (vpx_codec_dec_init(&codec, decoder->interface(), NULL, 0))
114233d2500723e5594f3e7c70896ffeeef32b9c950ywan    die_codec(&codec, "Failed to initialize decoder.");
115233d2500723e5594f3e7c70896ffeeef32b9c950ywan
116233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (vpx_video_reader_read_frame(reader)) {
117233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_codec_iter_t iter = NULL;
118233d2500723e5594f3e7c70896ffeeef32b9c950ywan    vpx_image_t *img = NULL;
119233d2500723e5594f3e7c70896ffeeef32b9c950ywan    size_t frame_size = 0;
120233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int skip;
121233d2500723e5594f3e7c70896ffeeef32b9c950ywan    const unsigned char *frame = vpx_video_reader_get_frame(reader,
122233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                                            &frame_size);
123233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (vpx_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0))
124233d2500723e5594f3e7c70896ffeeef32b9c950ywan      die_codec(&codec, "Failed to decode frame.");
125233d2500723e5594f3e7c70896ffeeef32b9c950ywan
126233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ++frame_cnt;
127233d2500723e5594f3e7c70896ffeeef32b9c950ywan
128233d2500723e5594f3e7c70896ffeeef32b9c950ywan    skip = (is_range && frame_cnt >= n && frame_cnt <= m) ||
129233d2500723e5594f3e7c70896ffeeef32b9c950ywan           (!is_range && m - (frame_cnt - 1) % m <= n);
130233d2500723e5594f3e7c70896ffeeef32b9c950ywan
131233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!skip) {
132233d2500723e5594f3e7c70896ffeeef32b9c950ywan      putc('.', stdout);
133233d2500723e5594f3e7c70896ffeeef32b9c950ywan
134233d2500723e5594f3e7c70896ffeeef32b9c950ywan      while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL)
135233d2500723e5594f3e7c70896ffeeef32b9c950ywan        vpx_img_write(img, outfile);
136233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else {
137233d2500723e5594f3e7c70896ffeeef32b9c950ywan      putc('X', stdout);
138233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
139233d2500723e5594f3e7c70896ffeeef32b9c950ywan
140233d2500723e5594f3e7c70896ffeeef32b9c950ywan    fflush(stdout);
141233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
142233d2500723e5594f3e7c70896ffeeef32b9c950ywan
143233d2500723e5594f3e7c70896ffeeef32b9c950ywan  printf("Processed %d frames.\n", frame_cnt);
144233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (vpx_codec_destroy(&codec))
145233d2500723e5594f3e7c70896ffeeef32b9c950ywan    die_codec(&codec, "Failed to destroy codec.");
146233d2500723e5594f3e7c70896ffeeef32b9c950ywan
147233d2500723e5594f3e7c70896ffeeef32b9c950ywan  printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n",
148233d2500723e5594f3e7c70896ffeeef32b9c950ywan         info->frame_width, info->frame_height, argv[2]);
149233d2500723e5594f3e7c70896ffeeef32b9c950ywan
150233d2500723e5594f3e7c70896ffeeef32b9c950ywan  vpx_video_reader_close(reader);
151233d2500723e5594f3e7c70896ffeeef32b9c950ywan  fclose(outfile);
152233d2500723e5594f3e7c70896ffeeef32b9c950ywan
153233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return EXIT_SUCCESS;
154233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
155