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 Partial Drops Example 12233d2500723e5594f3e7c70896ffeeef32b9c950ywan// ========================= 13233d2500723e5594f3e7c70896ffeeef32b9c950ywan// 14233d2500723e5594f3e7c70896ffeeef32b9c950ywan// This is an example utility which drops a series of frames (or parts of 15233d2500723e5594f3e7c70896ffeeef32b9c950ywan// frames), as specified on the command line. This is useful for observing the 16233d2500723e5594f3e7c70896ffeeef32b9c950ywan// error recovery 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_partial_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_partial_drops in.ivf out.i420 3/7 42233d2500723e5594f3e7c70896ffeeef32b9c950ywan// 43233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Dropping Random Parts Of Frames 44233d2500723e5594f3e7c70896ffeeef32b9c950ywan// ------------------------------- 45233d2500723e5594f3e7c70896ffeeef32b9c950ywan// A third argument tuple is available to split the frame into 1500 bytes pieces 46233d2500723e5594f3e7c70896ffeeef32b9c950ywan// and randomly drop pieces rather than frames. The frame will be split at 47233d2500723e5594f3e7c70896ffeeef32b9c950ywan// partition boundaries where possible. The following example will seed the RNG 48233d2500723e5594f3e7c70896ffeeef32b9c950ywan// with the seed 123 and drop approximately 5% of the pieces. Pieces which 49233d2500723e5594f3e7c70896ffeeef32b9c950ywan// are depending on an already dropped piece will also be dropped. 50233d2500723e5594f3e7c70896ffeeef32b9c950ywan// 51233d2500723e5594f3e7c70896ffeeef32b9c950ywan// $ ./decode_with_partial_drops in.ivf out.i420 5,123 52233d2500723e5594f3e7c70896ffeeef32b9c950ywan// 53233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Extra Variables 54233d2500723e5594f3e7c70896ffeeef32b9c950ywan// --------------- 55233d2500723e5594f3e7c70896ffeeef32b9c950ywan// This example maintains the pattern passed on the command line in the 56233d2500723e5594f3e7c70896ffeeef32b9c950ywan// `n`, `m`, and `is_range` variables: 57233d2500723e5594f3e7c70896ffeeef32b9c950ywan// 58233d2500723e5594f3e7c70896ffeeef32b9c950ywan// Making The Drop Decision 59233d2500723e5594f3e7c70896ffeeef32b9c950ywan// ------------------------ 60233d2500723e5594f3e7c70896ffeeef32b9c950ywan// The example decides whether to drop the frame based on the current 61233d2500723e5594f3e7c70896ffeeef32b9c950ywan// frame number, immediately before decoding the frame. 62233d2500723e5594f3e7c70896ffeeef32b9c950ywan 63233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <stdarg.h> 64233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <stdio.h> 65233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <stdlib.h> 66233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <string.h> 67233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define VPX_CODEC_DISABLE_COMPAT 1 68233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "./vpx_config.h" 69233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx/vp8dx.h" 70233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "vpx/vpx_decoder.h" 71233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define interface (vpx_codec_vp8_dx()) 72233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <time.h> 73233d2500723e5594f3e7c70896ffeeef32b9c950ywan 74233d2500723e5594f3e7c70896ffeeef32b9c950ywan 75233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define IVF_FILE_HDR_SZ (32) 76233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define IVF_FRAME_HDR_SZ (12) 77233d2500723e5594f3e7c70896ffeeef32b9c950ywan 78233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic unsigned int mem_get_le32(const unsigned char *mem) { 79233d2500723e5594f3e7c70896ffeeef32b9c950ywan return (mem[3] << 24)|(mem[2] << 16)|(mem[1] << 8)|(mem[0]); 80233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 81233d2500723e5594f3e7c70896ffeeef32b9c950ywan 82233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void die(const char *fmt, ...) { 83233d2500723e5594f3e7c70896ffeeef32b9c950ywan va_list ap; 84233d2500723e5594f3e7c70896ffeeef32b9c950ywan 85233d2500723e5594f3e7c70896ffeeef32b9c950ywan va_start(ap, fmt); 86233d2500723e5594f3e7c70896ffeeef32b9c950ywan vprintf(fmt, ap); 87233d2500723e5594f3e7c70896ffeeef32b9c950ywan if(fmt[strlen(fmt)-1] != '\n') 88233d2500723e5594f3e7c70896ffeeef32b9c950ywan printf("\n"); 89233d2500723e5594f3e7c70896ffeeef32b9c950ywan exit(EXIT_FAILURE); 90233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 91233d2500723e5594f3e7c70896ffeeef32b9c950ywan 92233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void die_codec(vpx_codec_ctx_t *ctx, const char *s) { 93233d2500723e5594f3e7c70896ffeeef32b9c950ywan const char *detail = vpx_codec_error_detail(ctx); 94233d2500723e5594f3e7c70896ffeeef32b9c950ywan 95233d2500723e5594f3e7c70896ffeeef32b9c950ywan printf("%s: %s\n", s, vpx_codec_error(ctx)); 96233d2500723e5594f3e7c70896ffeeef32b9c950ywan if(detail) 97233d2500723e5594f3e7c70896ffeeef32b9c950ywan printf(" %s\n",detail); 98233d2500723e5594f3e7c70896ffeeef32b9c950ywan exit(EXIT_FAILURE); 99233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 100233d2500723e5594f3e7c70896ffeeef32b9c950ywan 101233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct parsed_header 102233d2500723e5594f3e7c70896ffeeef32b9c950ywan{ 103233d2500723e5594f3e7c70896ffeeef32b9c950ywan char key_frame; 104233d2500723e5594f3e7c70896ffeeef32b9c950ywan int version; 105233d2500723e5594f3e7c70896ffeeef32b9c950ywan char show_frame; 106233d2500723e5594f3e7c70896ffeeef32b9c950ywan int first_part_size; 107233d2500723e5594f3e7c70896ffeeef32b9c950ywan}; 108233d2500723e5594f3e7c70896ffeeef32b9c950ywan 109233d2500723e5594f3e7c70896ffeeef32b9c950ywanint next_packet(struct parsed_header* hdr, int pos, int length, int mtu) 110233d2500723e5594f3e7c70896ffeeef32b9c950ywan{ 111233d2500723e5594f3e7c70896ffeeef32b9c950ywan int size = 0; 112233d2500723e5594f3e7c70896ffeeef32b9c950ywan int remaining = length - pos; 113233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Uncompressed part is 3 bytes for P frames and 10 bytes for I frames */ 114233d2500723e5594f3e7c70896ffeeef32b9c950ywan int uncomp_part_size = (hdr->key_frame ? 10 : 3); 115233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* number of bytes yet to send from header and the first partition */ 116233d2500723e5594f3e7c70896ffeeef32b9c950ywan int remainFirst = uncomp_part_size + hdr->first_part_size - pos; 117233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (remainFirst > 0) 118233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 119233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (remainFirst <= mtu) 120233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 121233d2500723e5594f3e7c70896ffeeef32b9c950ywan size = remainFirst; 122233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 123233d2500723e5594f3e7c70896ffeeef32b9c950ywan else 124233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 125233d2500723e5594f3e7c70896ffeeef32b9c950ywan size = mtu; 126233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 127233d2500723e5594f3e7c70896ffeeef32b9c950ywan 128233d2500723e5594f3e7c70896ffeeef32b9c950ywan return size; 129233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 130233d2500723e5594f3e7c70896ffeeef32b9c950ywan 131233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* second partition; just slot it up according to MTU */ 132233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (remaining <= mtu) 133233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 134233d2500723e5594f3e7c70896ffeeef32b9c950ywan size = remaining; 135233d2500723e5594f3e7c70896ffeeef32b9c950ywan return size; 136233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 137233d2500723e5594f3e7c70896ffeeef32b9c950ywan return mtu; 138233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 139233d2500723e5594f3e7c70896ffeeef32b9c950ywan 140233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid throw_packets(unsigned char* frame, int* size, int loss_rate, 141233d2500723e5594f3e7c70896ffeeef32b9c950ywan int* thrown, int* kept) 142233d2500723e5594f3e7c70896ffeeef32b9c950ywan{ 143233d2500723e5594f3e7c70896ffeeef32b9c950ywan unsigned char loss_frame[256*1024]; 144233d2500723e5594f3e7c70896ffeeef32b9c950ywan int pkg_size = 1; 145233d2500723e5594f3e7c70896ffeeef32b9c950ywan int pos = 0; 146233d2500723e5594f3e7c70896ffeeef32b9c950ywan int loss_pos = 0; 147233d2500723e5594f3e7c70896ffeeef32b9c950ywan struct parsed_header hdr; 148233d2500723e5594f3e7c70896ffeeef32b9c950ywan unsigned int tmp; 149233d2500723e5594f3e7c70896ffeeef32b9c950ywan int mtu = 1500; 150233d2500723e5594f3e7c70896ffeeef32b9c950ywan 151233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (*size < 3) 152233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 153233d2500723e5594f3e7c70896ffeeef32b9c950ywan return; 154233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 155233d2500723e5594f3e7c70896ffeeef32b9c950ywan putc('|', stdout); 156233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* parse uncompressed 3 bytes */ 157233d2500723e5594f3e7c70896ffeeef32b9c950ywan tmp = (frame[2] << 16) | (frame[1] << 8) | frame[0]; 158233d2500723e5594f3e7c70896ffeeef32b9c950ywan hdr.key_frame = !(tmp & 0x1); /* inverse logic */ 159233d2500723e5594f3e7c70896ffeeef32b9c950ywan hdr.version = (tmp >> 1) & 0x7; 160233d2500723e5594f3e7c70896ffeeef32b9c950ywan hdr.show_frame = (tmp >> 4) & 0x1; 161233d2500723e5594f3e7c70896ffeeef32b9c950ywan hdr.first_part_size = (tmp >> 5) & 0x7FFFF; 162233d2500723e5594f3e7c70896ffeeef32b9c950ywan 163233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* don't drop key frames */ 164233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (hdr.key_frame) 165233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 166233d2500723e5594f3e7c70896ffeeef32b9c950ywan int i; 167233d2500723e5594f3e7c70896ffeeef32b9c950ywan *kept = *size/mtu + ((*size % mtu > 0) ? 1 : 0); /* approximate */ 168233d2500723e5594f3e7c70896ffeeef32b9c950ywan for (i=0; i < *kept; i++) 169233d2500723e5594f3e7c70896ffeeef32b9c950ywan putc('.', stdout); 170233d2500723e5594f3e7c70896ffeeef32b9c950ywan return; 171233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 172233d2500723e5594f3e7c70896ffeeef32b9c950ywan 173233d2500723e5594f3e7c70896ffeeef32b9c950ywan while ((pkg_size = next_packet(&hdr, pos, *size, mtu)) > 0) 174233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 175233d2500723e5594f3e7c70896ffeeef32b9c950ywan int loss_event = ((rand() + 1.0)/(RAND_MAX + 1.0) < loss_rate/100.0); 176233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (*thrown == 0 && !loss_event) 177233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 178233d2500723e5594f3e7c70896ffeeef32b9c950ywan memcpy(loss_frame + loss_pos, frame + pos, pkg_size); 179233d2500723e5594f3e7c70896ffeeef32b9c950ywan loss_pos += pkg_size; 180233d2500723e5594f3e7c70896ffeeef32b9c950ywan (*kept)++; 181233d2500723e5594f3e7c70896ffeeef32b9c950ywan putc('.', stdout); 182233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 183233d2500723e5594f3e7c70896ffeeef32b9c950ywan else 184233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 185233d2500723e5594f3e7c70896ffeeef32b9c950ywan (*thrown)++; 186233d2500723e5594f3e7c70896ffeeef32b9c950ywan putc('X', stdout); 187233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 188233d2500723e5594f3e7c70896ffeeef32b9c950ywan pos += pkg_size; 189233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 190233d2500723e5594f3e7c70896ffeeef32b9c950ywan memcpy(frame, loss_frame, loss_pos); 191233d2500723e5594f3e7c70896ffeeef32b9c950ywan memset(frame + loss_pos, 0, *size - loss_pos); 192233d2500723e5594f3e7c70896ffeeef32b9c950ywan *size = loss_pos; 193233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 194233d2500723e5594f3e7c70896ffeeef32b9c950ywan 195233d2500723e5594f3e7c70896ffeeef32b9c950ywanint main(int argc, char **argv) { 196233d2500723e5594f3e7c70896ffeeef32b9c950ywan FILE *infile, *outfile; 197233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_codec_ctx_t codec; 198233d2500723e5594f3e7c70896ffeeef32b9c950ywan int flags = 0, frame_cnt = 0; 199233d2500723e5594f3e7c70896ffeeef32b9c950ywan unsigned char file_hdr[IVF_FILE_HDR_SZ]; 200233d2500723e5594f3e7c70896ffeeef32b9c950ywan unsigned char frame_hdr[IVF_FRAME_HDR_SZ]; 201233d2500723e5594f3e7c70896ffeeef32b9c950ywan unsigned char frame[256*1024]; 202233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_codec_err_t res; 203233d2500723e5594f3e7c70896ffeeef32b9c950ywan int n, m, mode; 204233d2500723e5594f3e7c70896ffeeef32b9c950ywan unsigned int seed; 205233d2500723e5594f3e7c70896ffeeef32b9c950ywan int thrown=0, kept=0; 206233d2500723e5594f3e7c70896ffeeef32b9c950ywan int thrown_frame=0, kept_frame=0; 207233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_codec_dec_cfg_t dec_cfg = {0}; 208233d2500723e5594f3e7c70896ffeeef32b9c950ywan 209233d2500723e5594f3e7c70896ffeeef32b9c950ywan (void)res; 210233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Open files */ 211233d2500723e5594f3e7c70896ffeeef32b9c950ywan if(argc < 4 || argc > 6) 212233d2500723e5594f3e7c70896ffeeef32b9c950ywan die("Usage: %s <infile> <outfile> [-t <num threads>] <N-M|N/M|L,S>\n", 213233d2500723e5594f3e7c70896ffeeef32b9c950ywan argv[0]); 214233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 215233d2500723e5594f3e7c70896ffeeef32b9c950ywan char *nptr; 216233d2500723e5594f3e7c70896ffeeef32b9c950ywan int arg_num = 3; 217233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (argc == 6 && strncmp(argv[arg_num++], "-t", 2) == 0) 218233d2500723e5594f3e7c70896ffeeef32b9c950ywan dec_cfg.threads = strtol(argv[arg_num++], NULL, 0); 219233d2500723e5594f3e7c70896ffeeef32b9c950ywan n = strtol(argv[arg_num], &nptr, 0); 220233d2500723e5594f3e7c70896ffeeef32b9c950ywan mode = (*nptr == '\0' || *nptr == ',') ? 2 : (*nptr == '-') ? 1 : 0; 221233d2500723e5594f3e7c70896ffeeef32b9c950ywan 222233d2500723e5594f3e7c70896ffeeef32b9c950ywan m = strtol(nptr+1, NULL, 0); 223233d2500723e5594f3e7c70896ffeeef32b9c950ywan if((!n && !m) || (*nptr != '-' && *nptr != '/' && 224233d2500723e5594f3e7c70896ffeeef32b9c950ywan *nptr != '\0' && *nptr != ',')) 225233d2500723e5594f3e7c70896ffeeef32b9c950ywan die("Couldn't parse pattern %s\n", argv[3]); 226233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 227233d2500723e5594f3e7c70896ffeeef32b9c950ywan seed = (m > 0) ? m : (unsigned int)time(NULL); 228233d2500723e5594f3e7c70896ffeeef32b9c950ywan srand(seed);thrown_frame = 0; 229233d2500723e5594f3e7c70896ffeeef32b9c950ywan printf("Seed: %u\n", seed); 230233d2500723e5594f3e7c70896ffeeef32b9c950ywan printf("Threads: %d\n", dec_cfg.threads); 231233d2500723e5594f3e7c70896ffeeef32b9c950ywan if(!(infile = fopen(argv[1], "rb"))) 232233d2500723e5594f3e7c70896ffeeef32b9c950ywan die("Failed to open %s for reading", argv[1]); 233233d2500723e5594f3e7c70896ffeeef32b9c950ywan if(!(outfile = fopen(argv[2], "wb"))) 234233d2500723e5594f3e7c70896ffeeef32b9c950ywan die("Failed to open %s for writing", argv[2]); 235233d2500723e5594f3e7c70896ffeeef32b9c950ywan 236233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Read file header */ 237233d2500723e5594f3e7c70896ffeeef32b9c950ywan if(!(fread(file_hdr, 1, IVF_FILE_HDR_SZ, infile) == IVF_FILE_HDR_SZ 238233d2500723e5594f3e7c70896ffeeef32b9c950ywan && file_hdr[0]=='D' && file_hdr[1]=='K' && file_hdr[2]=='I' 239233d2500723e5594f3e7c70896ffeeef32b9c950ywan && file_hdr[3]=='F')) 240233d2500723e5594f3e7c70896ffeeef32b9c950ywan die("%s is not an IVF file.", argv[1]); 241233d2500723e5594f3e7c70896ffeeef32b9c950ywan 242233d2500723e5594f3e7c70896ffeeef32b9c950ywan printf("Using %s\n",vpx_codec_iface_name(interface)); 243233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Initialize codec */ 244233d2500723e5594f3e7c70896ffeeef32b9c950ywan flags = VPX_CODEC_USE_ERROR_CONCEALMENT; 245233d2500723e5594f3e7c70896ffeeef32b9c950ywan res = vpx_codec_dec_init(&codec, interface, &dec_cfg, flags); 246233d2500723e5594f3e7c70896ffeeef32b9c950ywan if(res) 247233d2500723e5594f3e7c70896ffeeef32b9c950ywan die_codec(&codec, "Failed to initialize decoder"); 248233d2500723e5594f3e7c70896ffeeef32b9c950ywan 249233d2500723e5594f3e7c70896ffeeef32b9c950ywan 250233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Read each frame */ 251233d2500723e5594f3e7c70896ffeeef32b9c950ywan while(fread(frame_hdr, 1, IVF_FRAME_HDR_SZ, infile) == IVF_FRAME_HDR_SZ) { 252233d2500723e5594f3e7c70896ffeeef32b9c950ywan int frame_sz = mem_get_le32(frame_hdr); 253233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_codec_iter_t iter = NULL; 254233d2500723e5594f3e7c70896ffeeef32b9c950ywan vpx_image_t *img; 255233d2500723e5594f3e7c70896ffeeef32b9c950ywan 256233d2500723e5594f3e7c70896ffeeef32b9c950ywan 257233d2500723e5594f3e7c70896ffeeef32b9c950ywan frame_cnt++; 258233d2500723e5594f3e7c70896ffeeef32b9c950ywan if(frame_sz > sizeof(frame)) 259233d2500723e5594f3e7c70896ffeeef32b9c950ywan die("Frame %d data too big for example code buffer", frame_sz); 260233d2500723e5594f3e7c70896ffeeef32b9c950ywan if(fread(frame, 1, frame_sz, infile) != frame_sz) 261233d2500723e5594f3e7c70896ffeeef32b9c950ywan die("Frame %d failed to read complete frame", frame_cnt); 262233d2500723e5594f3e7c70896ffeeef32b9c950ywan 263233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Decide whether to throw parts of the frame or the whole frame 264233d2500723e5594f3e7c70896ffeeef32b9c950ywan depending on the drop mode */ 265233d2500723e5594f3e7c70896ffeeef32b9c950ywan thrown_frame = 0; 266233d2500723e5594f3e7c70896ffeeef32b9c950ywan kept_frame = 0; 267233d2500723e5594f3e7c70896ffeeef32b9c950ywan switch (mode) 268233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 269233d2500723e5594f3e7c70896ffeeef32b9c950ywan case 0: 270233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (m - (frame_cnt-1)%m <= n) 271233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 272233d2500723e5594f3e7c70896ffeeef32b9c950ywan frame_sz = 0; 273233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 274233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 275233d2500723e5594f3e7c70896ffeeef32b9c950ywan case 1: 276233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (frame_cnt >= n && frame_cnt <= m) 277233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 278233d2500723e5594f3e7c70896ffeeef32b9c950ywan frame_sz = 0; 279233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 280233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 281233d2500723e5594f3e7c70896ffeeef32b9c950ywan case 2: 282233d2500723e5594f3e7c70896ffeeef32b9c950ywan throw_packets(frame, &frame_sz, n, &thrown_frame, &kept_frame); 283233d2500723e5594f3e7c70896ffeeef32b9c950ywan break; 284233d2500723e5594f3e7c70896ffeeef32b9c950ywan default: break; 285233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 286233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (mode < 2) 287233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 288233d2500723e5594f3e7c70896ffeeef32b9c950ywan if (frame_sz == 0) 289233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 290233d2500723e5594f3e7c70896ffeeef32b9c950ywan putc('X', stdout); 291233d2500723e5594f3e7c70896ffeeef32b9c950ywan thrown_frame++; 292233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 293233d2500723e5594f3e7c70896ffeeef32b9c950ywan else 294233d2500723e5594f3e7c70896ffeeef32b9c950ywan { 295233d2500723e5594f3e7c70896ffeeef32b9c950ywan putc('.', stdout); 296233d2500723e5594f3e7c70896ffeeef32b9c950ywan kept_frame++; 297233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 298233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 299233d2500723e5594f3e7c70896ffeeef32b9c950ywan thrown += thrown_frame; 300233d2500723e5594f3e7c70896ffeeef32b9c950ywan kept += kept_frame; 301233d2500723e5594f3e7c70896ffeeef32b9c950ywan fflush(stdout); 302233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Decode the frame */ 303233d2500723e5594f3e7c70896ffeeef32b9c950ywan if(vpx_codec_decode(&codec, frame, frame_sz, NULL, 0)) 304233d2500723e5594f3e7c70896ffeeef32b9c950ywan die_codec(&codec, "Failed to decode frame"); 305233d2500723e5594f3e7c70896ffeeef32b9c950ywan 306233d2500723e5594f3e7c70896ffeeef32b9c950ywan /* Write decoded data to disk */ 307233d2500723e5594f3e7c70896ffeeef32b9c950ywan while((img = vpx_codec_get_frame(&codec, &iter))) { 308233d2500723e5594f3e7c70896ffeeef32b9c950ywan unsigned int plane, y; 309233d2500723e5594f3e7c70896ffeeef32b9c950ywan 310233d2500723e5594f3e7c70896ffeeef32b9c950ywan for(plane=0; plane < 3; plane++) { 311233d2500723e5594f3e7c70896ffeeef32b9c950ywan unsigned char *buf =img->planes[plane]; 312233d2500723e5594f3e7c70896ffeeef32b9c950ywan 313233d2500723e5594f3e7c70896ffeeef32b9c950ywan for(y=0; y < (plane ? (img->d_h + 1) >> 1 : img->d_h); y++) { 314233d2500723e5594f3e7c70896ffeeef32b9c950ywan (void) fwrite(buf, 1, (plane ? (img->d_w + 1) >> 1 : img->d_w), 315233d2500723e5594f3e7c70896ffeeef32b9c950ywan outfile); 316233d2500723e5594f3e7c70896ffeeef32b9c950ywan buf += img->stride[plane]; 317233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 318233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 319233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 320233d2500723e5594f3e7c70896ffeeef32b9c950ywan } 321233d2500723e5594f3e7c70896ffeeef32b9c950ywan printf("Processed %d frames.\n",frame_cnt); 322233d2500723e5594f3e7c70896ffeeef32b9c950ywan if(vpx_codec_destroy(&codec)) 323233d2500723e5594f3e7c70896ffeeef32b9c950ywan die_codec(&codec, "Failed to destroy codec"); 324233d2500723e5594f3e7c70896ffeeef32b9c950ywan 325233d2500723e5594f3e7c70896ffeeef32b9c950ywan fclose(outfile); 326233d2500723e5594f3e7c70896ffeeef32b9c950ywan fclose(infile); 327233d2500723e5594f3e7c70896ffeeef32b9c950ywan return EXIT_SUCCESS; 328233d2500723e5594f3e7c70896ffeeef32b9c950ywan} 329