1 @TEMPLATE decoder_tmpl.c
2 Decode With Partial Drops Example
3 =========================
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
5 This is an example utility which drops a series of frames (or parts of frames),
6 as specified on the command line. This is useful for observing the error
7 recovery features of the codec.
8 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
10 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_INCLUDES
12 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_INCLUDES
14 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ HELPERS
23 int next_packet(struct parsed_header* hdr, int pos, int length, int mtu)
26 int remaining = length - pos;
27 /* Uncompressed part is 3 bytes for P frames and 10 bytes for I frames */
28 int uncomp_part_size = (hdr->key_frame ? 10 : 3);
29 /* number of bytes yet to send from header and the first partition */
30 int remainFirst = uncomp_part_size + hdr->first_part_size - pos;
33 if (remainFirst <= mtu)
45 /* second partition; just slot it up according to MTU */
54 void throw_packets(unsigned char* frame, int* size, int loss_rate,
55 int* thrown, int* kept)
57 unsigned char loss_frame[256*1024];
61 struct parsed_header hdr;
70 /* parse uncompressed 3 bytes */
71 tmp = (frame[2] << 16) | (frame[1] << 8) | frame[0];
72 hdr.key_frame = !(tmp & 0x1); /* inverse logic */
73 hdr.version = (tmp >> 1) & 0x7;
74 hdr.show_frame = (tmp >> 4) & 0x1;
75 hdr.first_part_size = (tmp >> 5) & 0x7FFFF;
77 /* don't drop key frames */
81 *kept = *size/mtu + ((*size % mtu > 0) ? 1 : 0); /* approximate */
82 for (i=0; i < *kept; i++)
87 while ((pkg_size = next_packet(&hdr, pos, *size, mtu)) > 0)
89 int loss_event = ((rand() + 1.0)/(RAND_MAX + 1.0) < loss_rate/100.0);
90 if (*thrown == 0 && !loss_event)
92 memcpy(loss_frame + loss_pos, frame + pos, pkg_size);
104 memcpy(frame, loss_frame, loss_pos);
105 memset(frame + loss_pos, 0, *size - loss_pos);
108 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ HELPERS
110 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INIT
111 /* Initialize codec */
112 flags = VPX_CODEC_USE_ERROR_CONCEALMENT;
113 res = vpx_codec_dec_init(&codec, interface, &dec_cfg, flags);
115 die_codec(&codec, "Failed to initialize decoder");
117 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INIT
121 This example adds a single argument to the `simple_decoder` example,
122 which specifies the range or pattern of frames to drop. The parameter is
125 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
126 if(argc < 4 || argc > 6)
127 die("Usage: %s <infile> <outfile> [-t <num threads>] <N-M|N/M|L,S>\n",
132 if (argc == 6 && strncmp(argv[arg_num++], "-t", 2) == 0)
133 dec_cfg.threads = strtol(argv[arg_num++], NULL, 0);
134 n = strtol(argv[arg_num], &nptr, 0);
135 mode = (*nptr == '\0' || *nptr == ',') ? 2 : (*nptr == '-') ? 1 : 0;
137 m = strtol(nptr+1, NULL, 0);
138 if((!n && !m) || (*nptr != '-' && *nptr != '/' &&
139 *nptr != '\0' && *nptr != ','))
140 die("Couldn't parse pattern %s\n", argv[3]);
142 seed = (m > 0) ? m : (unsigned int)time(NULL);
143 srand(seed);thrown_frame = 0;
144 printf("Seed: %u\n", seed);
145 printf("Threads: %d\n", dec_cfg.threads);
146 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
149 Dropping A Range Of Frames
150 --------------------------
151 To drop a range of frames, specify the starting frame and the ending
152 frame to drop, separated by a dash. The following command will drop
153 frames 5 through 10 (base 1).
155 $ ./decode_with_partial_drops in.ivf out.i420 5-10
158 Dropping A Pattern Of Frames
159 ----------------------------
160 To drop a pattern of frames, specify the number of frames to drop and
161 the number of frames after which to repeat the pattern, separated by
162 a forward-slash. The following command will drop 3 of 7 frames.
163 Specifically, it will decode 4 frames, then drop 3 frames, and then
166 $ ./decode_with_partial_drops in.ivf out.i420 3/7
168 Dropping Random Parts Of Frames
169 -------------------------------
170 A third argument tuple is available to split the frame into 1500 bytes pieces
171 and randomly drop pieces rather than frames. The frame will be split at
172 partition boundaries where possible. The following example will seed the RNG
173 with the seed 123 and drop approximately 5% of the pieces. Pieces which
174 are depending on an already dropped piece will also be dropped.
176 $ ./decode_with_partial_drops in.ivf out.i420 5,123
181 This example maintains the pattern passed on the command line in the
182 `n`, `m`, and `is_range` variables:
184 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_VARS
187 int thrown=0, kept=0;
188 int thrown_frame=0, kept_frame=0;
189 vpx_codec_dec_cfg_t dec_cfg = {0};
190 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_VARS
193 Making The Drop Decision
194 ------------------------
195 The example decides whether to drop the frame based on the current
196 frame number, immediately before decoding the frame.
198 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PRE_DECODE
199 /* Decide whether to throw parts of the frame or the whole frame
200 depending on the drop mode */
206 if (m - (frame_cnt-1)%m <= n)
212 if (frame_cnt >= n && frame_cnt <= m)
218 throw_packets(frame, &frame_sz, n, &thrown_frame, &kept_frame);
235 thrown += thrown_frame;
238 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PRE_DECODE