1b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian/*
2b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian *
4b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian *  Use of this source code is governed by a BSD-style license
5b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian *  that can be found in the LICENSE file in the root of the source
6b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian *  tree. An additional intellectual property rights grant can be found
7b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian *  in the file PATENTS.  All contributing project authors may
8b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian *  be found in the AUTHORS file in the root of the source tree.
9b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian */
10b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
11b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// Decode With Partial Drops Example
12b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// =========================
13b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian//
14b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// This is an example utility which drops a series of frames (or parts of
15b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// frames), as specified on the command line. This is useful for observing the
16b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// error recovery features of the codec.
17b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian//
18b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// Usage
19b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// -----
20b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// This example adds a single argument to the `simple_decoder` example,
21b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// which specifies the range or pattern of frames to drop. The parameter is
22b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// parsed as follows.
23b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian//
24b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// Dropping A Range Of Frames
25b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// --------------------------
26b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// To drop a range of frames, specify the starting frame and the ending
27b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// frame to drop, separated by a dash. The following command will drop
28b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// frames 5 through 10 (base 1).
29b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian//
30b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian//  $ ./decode_with_partial_drops in.ivf out.i420 5-10
31b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian//
32b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian//
33b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// Dropping A Pattern Of Frames
34b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// ----------------------------
35b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// To drop a pattern of frames, specify the number of frames to drop and
36b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// the number of frames after which to repeat the pattern, separated by
37b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// a forward-slash. The following command will drop 3 of 7 frames.
38b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// Specifically, it will decode 4 frames, then drop 3 frames, and then
39b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// repeat.
40b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian//
41b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian//  $ ./decode_with_partial_drops in.ivf out.i420 3/7
42b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian//
43b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// Dropping Random Parts Of Frames
44b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// -------------------------------
45b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// A third argument tuple is available to split the frame into 1500 bytes pieces
46b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// and randomly drop pieces rather than frames. The frame will be split at
47b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// partition boundaries where possible. The following example will seed the RNG
48b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// with the seed 123 and drop approximately 5% of the pieces. Pieces which
49b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// are depending on an already dropped piece will also be dropped.
50b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian//
51b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian//  $ ./decode_with_partial_drops in.ivf out.i420 5,123
52b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian//
53b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// Extra Variables
54b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// ---------------
55b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// This example maintains the pattern passed on the command line in the
56b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// `n`, `m`, and `is_range` variables:
57b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian//
58b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// Making The Drop Decision
59b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// ------------------------
60b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// The example decides whether to drop the frame based on the current
61b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// frame number, immediately before decoding the frame.
62b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
63b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#include <stdarg.h>
64b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#include <stdio.h>
65b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#include <stdlib.h>
66b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#include <string.h>
67b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#define VPX_CODEC_DISABLE_COMPAT 1
68b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#include "./vpx_config.h"
69b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#include "vpx/vp8dx.h"
70b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#include "vpx/vpx_decoder.h"
71b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#define interface (vpx_codec_vp8_dx())
72b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#include <time.h>
73b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
74b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
75b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#define IVF_FILE_HDR_SZ  (32)
76b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#define IVF_FRAME_HDR_SZ (12)
77b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
78b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianstatic unsigned int mem_get_le32(const unsigned char *mem) {
79b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return (mem[3] << 24)|(mem[2] << 16)|(mem[1] << 8)|(mem[0]);
80b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian}
81b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
82b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianstatic void die(const char *fmt, ...) {
83b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    va_list ap;
84b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
85b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    va_start(ap, fmt);
86b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    vprintf(fmt, ap);
87b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if(fmt[strlen(fmt)-1] != '\n')
88b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        printf("\n");
89b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    exit(EXIT_FAILURE);
90b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian}
91b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
92b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianstatic void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
93b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    const char *detail = vpx_codec_error_detail(ctx);
94b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
95b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    printf("%s: %s\n", s, vpx_codec_error(ctx));
96b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if(detail)
97b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        printf("    %s\n",detail);
98b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    exit(EXIT_FAILURE);
99b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian}
100b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
101b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianstruct parsed_header
102b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian{
103b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    char key_frame;
104b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    int version;
105b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    char show_frame;
106b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    int first_part_size;
107b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian};
108b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
109b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianint next_packet(struct parsed_header* hdr, int pos, int length, int mtu)
110b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian{
111b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    int size = 0;
112b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    int remaining = length - pos;
113b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    /* Uncompressed part is 3 bytes for P frames and 10 bytes for I frames */
114b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    int uncomp_part_size = (hdr->key_frame ? 10 : 3);
115b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    /* number of bytes yet to send from header and the first partition */
116b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    int remainFirst = uncomp_part_size + hdr->first_part_size - pos;
117b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (remainFirst > 0)
118b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    {
119b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        if (remainFirst <= mtu)
120b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        {
121b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            size = remainFirst;
122b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        }
123b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        else
124b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        {
125b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            size = mtu;
126b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        }
127b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
128b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        return size;
129b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    }
130b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
131b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    /* second partition; just slot it up according to MTU */
132b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (remaining <= mtu)
133b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    {
134b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        size = remaining;
135b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        return size;
136b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    }
137b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return mtu;
138b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian}
139b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
140b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianvoid throw_packets(unsigned char* frame, int* size, int loss_rate,
141b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                   int* thrown, int* kept)
142b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian{
143b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    unsigned char loss_frame[256*1024];
144b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    int pkg_size = 1;
145b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    int pos = 0;
146b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    int loss_pos = 0;
147b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    struct parsed_header hdr;
148b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    unsigned int tmp;
149b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    int mtu = 1500;
150b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
151b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (*size < 3)
152b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    {
153b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        return;
154b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    }
155b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    putc('|', stdout);
156b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    /* parse uncompressed 3 bytes */
157b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    tmp = (frame[2] << 16) | (frame[1] << 8) | frame[0];
158b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    hdr.key_frame = !(tmp & 0x1); /* inverse logic */
159b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    hdr.version = (tmp >> 1) & 0x7;
160b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    hdr.show_frame = (tmp >> 4) & 0x1;
161b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    hdr.first_part_size = (tmp >> 5) & 0x7FFFF;
162b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
163b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    /* don't drop key frames */
164b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (hdr.key_frame)
165b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    {
166b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        int i;
167b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        *kept = *size/mtu + ((*size % mtu > 0) ? 1 : 0); /* approximate */
168b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        for (i=0; i < *kept; i++)
169b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            putc('.', stdout);
170b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        return;
171b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    }
172b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
173b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    while ((pkg_size = next_packet(&hdr, pos, *size, mtu)) > 0)
174b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    {
175b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        int loss_event = ((rand() + 1.0)/(RAND_MAX + 1.0) < loss_rate/100.0);
176b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        if (*thrown == 0 && !loss_event)
177b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        {
178b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            memcpy(loss_frame + loss_pos, frame + pos, pkg_size);
179b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            loss_pos += pkg_size;
180b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            (*kept)++;
181b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            putc('.', stdout);
182b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        }
183b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        else
184b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        {
185b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            (*thrown)++;
186b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            putc('X', stdout);
187b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        }
188b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        pos += pkg_size;
189b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    }
190b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    memcpy(frame, loss_frame, loss_pos);
191b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    memset(frame + loss_pos, 0, *size - loss_pos);
192b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    *size = loss_pos;
193b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian}
194b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
195b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianint main(int argc, char **argv) {
196b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    FILE            *infile, *outfile;
197b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    vpx_codec_ctx_t  codec;
198b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    int              flags = 0, frame_cnt = 0;
199b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    unsigned char    file_hdr[IVF_FILE_HDR_SZ];
200b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    unsigned char    frame_hdr[IVF_FRAME_HDR_SZ];
201b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    unsigned char    frame[256*1024];
202b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    vpx_codec_err_t  res;
203b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    int              n, m, mode;
204b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    unsigned int     seed;
205b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    int              thrown=0, kept=0;
206b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    int              thrown_frame=0, kept_frame=0;
207b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    vpx_codec_dec_cfg_t  dec_cfg = {0};
208b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
209b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    (void)res;
210b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    /* Open files */
211b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if(argc < 4 || argc > 6)
212b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        die("Usage: %s <infile> <outfile> [-t <num threads>] <N-M|N/M|L,S>\n",
213b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            argv[0]);
214b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    {
215b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        char *nptr;
216b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        int arg_num = 3;
217b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        if (argc == 6 && strncmp(argv[arg_num++], "-t", 2) == 0)
218b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            dec_cfg.threads = strtol(argv[arg_num++], NULL, 0);
219b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        n = strtol(argv[arg_num], &nptr, 0);
220b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        mode = (*nptr == '\0' || *nptr == ',') ? 2 : (*nptr == '-') ? 1 : 0;
221b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
222b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        m = strtol(nptr+1, NULL, 0);
223b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        if((!n && !m) || (*nptr != '-' && *nptr != '/' &&
224b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            *nptr != '\0' && *nptr != ','))
225b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            die("Couldn't parse pattern %s\n", argv[3]);
226b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    }
227b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    seed = (m > 0) ? m : (unsigned int)time(NULL);
228b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    srand(seed);thrown_frame = 0;
229b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    printf("Seed: %u\n", seed);
230b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    printf("Threads: %d\n", dec_cfg.threads);
231b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if(!(infile = fopen(argv[1], "rb")))
232b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        die("Failed to open %s for reading", argv[1]);
233b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if(!(outfile = fopen(argv[2], "wb")))
234b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        die("Failed to open %s for writing", argv[2]);
235b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
236b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    /* Read file header */
237b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if(!(fread(file_hdr, 1, IVF_FILE_HDR_SZ, infile) == IVF_FILE_HDR_SZ
238b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian         && file_hdr[0]=='D' && file_hdr[1]=='K' && file_hdr[2]=='I'
239b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian         && file_hdr[3]=='F'))
240b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        die("%s is not an IVF file.", argv[1]);
241b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
242b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    printf("Using %s\n",vpx_codec_iface_name(interface));
243b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    /* Initialize codec */
244b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    flags = VPX_CODEC_USE_ERROR_CONCEALMENT;
245b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    res = vpx_codec_dec_init(&codec, interface, &dec_cfg, flags);
246b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if(res)
247b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        die_codec(&codec, "Failed to initialize decoder");
248b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
249b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
250b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    /* Read each frame */
251b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    while(fread(frame_hdr, 1, IVF_FRAME_HDR_SZ, infile) == IVF_FRAME_HDR_SZ) {
252b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        int               frame_sz = mem_get_le32(frame_hdr);
253b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        vpx_codec_iter_t  iter = NULL;
254b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        vpx_image_t      *img;
255b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
256b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
257b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        frame_cnt++;
258b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        if(frame_sz > sizeof(frame))
259b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            die("Frame %d data too big for example code buffer", frame_sz);
260b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        if(fread(frame, 1, frame_sz, infile) != frame_sz)
261b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            die("Frame %d failed to read complete frame", frame_cnt);
262b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
263b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        /* Decide whether to throw parts of the frame or the whole frame
264b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian           depending on the drop mode */
265b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        thrown_frame = 0;
266b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        kept_frame = 0;
267b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        switch (mode)
268b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        {
269b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        case 0:
270b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            if (m - (frame_cnt-1)%m <= n)
271b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            {
272b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                frame_sz = 0;
273b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            }
274b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            break;
275b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        case 1:
276b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            if (frame_cnt >= n && frame_cnt <= m)
277b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            {
278b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                frame_sz = 0;
279b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            }
280b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            break;
281b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        case 2:
282b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            throw_packets(frame, &frame_sz, n, &thrown_frame, &kept_frame);
283b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            break;
284b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        default: break;
285b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        }
286b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        if (mode < 2)
287b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        {
288b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            if (frame_sz == 0)
289b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            {
290b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                putc('X', stdout);
291b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                thrown_frame++;
292b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            }
293b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            else
294b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            {
295b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                putc('.', stdout);
296b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                kept_frame++;
297b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            }
298b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        }
299b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        thrown += thrown_frame;
300b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        kept += kept_frame;
301b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        fflush(stdout);
302b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        /* Decode the frame */
303b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        if(vpx_codec_decode(&codec, frame, frame_sz, NULL, 0))
304b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            die_codec(&codec, "Failed to decode frame");
305b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
306b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        /* Write decoded data to disk */
307b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        while((img = vpx_codec_get_frame(&codec, &iter))) {
308b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            unsigned int plane, y;
309b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
310b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            for(plane=0; plane < 3; plane++) {
311b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                unsigned char *buf =img->planes[plane];
312b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
313b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                for(y=0; y < (plane ? (img->d_h + 1) >> 1 : img->d_h); y++) {
314b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                    (void) fwrite(buf, 1, (plane ? (img->d_w + 1) >> 1 : img->d_w),
315b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                                  outfile);
316b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                    buf += img->stride[plane];
317b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                }
318b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            }
319b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        }
320b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    }
321b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    printf("Processed %d frames.\n",frame_cnt);
322b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if(vpx_codec_destroy(&codec))
323b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        die_codec(&codec, "Failed to destroy codec");
324b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
325b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    fclose(outfile);
326b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    fclose(infile);
327b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return EXIT_SUCCESS;
328b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian}
329