1 /*
2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
3 *
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.
10 */
11
12 #include "common/ivfdec.h"
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17
18 #include "aom_ports/mem_ops.h"
19 #include "aom_ports/sanitizer.h"
20
21 static const char *IVF_SIGNATURE = "DKIF";
22
fix_framerate(int * num,int * den)23 static void fix_framerate(int *num, int *den) {
24 if (*den <= 0 || *den >= 1000000000 || *num <= 0 || *num >= 1000) {
25 // framerate seems to be invalid, just default to 30fps.
26 *num = 30;
27 *den = 1;
28 }
29 }
30
file_is_ivf(struct AvxInputContext * input_ctx)31 int file_is_ivf(struct AvxInputContext *input_ctx) {
32 char raw_hdr[32];
33 int is_ivf = 0;
34
35 if (fread(raw_hdr, 1, 32, input_ctx->file) == 32) {
36 if (memcmp(IVF_SIGNATURE, raw_hdr, 4) == 0) {
37 is_ivf = 1;
38
39 if (mem_get_le16(raw_hdr + 4) != 0) {
40 fprintf(stderr,
41 "Error: Unrecognized IVF version! This file may not"
42 " decode properly.");
43 }
44
45 input_ctx->fourcc = mem_get_le32(raw_hdr + 8);
46 input_ctx->width = mem_get_le16(raw_hdr + 12);
47 input_ctx->height = mem_get_le16(raw_hdr + 14);
48 input_ctx->framerate.numerator = mem_get_le32(raw_hdr + 16);
49 input_ctx->framerate.denominator = mem_get_le32(raw_hdr + 20);
50 fix_framerate(&input_ctx->framerate.numerator,
51 &input_ctx->framerate.denominator);
52 }
53 }
54
55 if (!is_ivf) {
56 rewind(input_ctx->file);
57 input_ctx->detect.buf_read = 0;
58 } else {
59 input_ctx->detect.position = 4;
60 }
61 return is_ivf;
62 }
63
ivf_read_frame(FILE * infile,uint8_t ** buffer,size_t * bytes_read,size_t * buffer_size,aom_codec_pts_t * pts)64 int ivf_read_frame(FILE *infile, uint8_t **buffer, size_t *bytes_read,
65 size_t *buffer_size, aom_codec_pts_t *pts) {
66 char raw_header[IVF_FRAME_HDR_SZ] = { 0 };
67 size_t frame_size = 0;
68
69 if (fread(raw_header, IVF_FRAME_HDR_SZ, 1, infile) != 1) {
70 if (!feof(infile)) warn("Failed to read frame size");
71 } else {
72 frame_size = mem_get_le32(raw_header);
73
74 if (frame_size > 256 * 1024 * 1024) {
75 warn("Read invalid frame size (%u)", (unsigned int)frame_size);
76 frame_size = 0;
77 }
78
79 if (frame_size > *buffer_size) {
80 uint8_t *new_buffer = (uint8_t *)realloc(*buffer, 2 * frame_size);
81
82 if (new_buffer) {
83 *buffer = new_buffer;
84 *buffer_size = 2 * frame_size;
85 } else {
86 warn("Failed to allocate compressed data buffer");
87 frame_size = 0;
88 }
89 }
90
91 if (pts) {
92 *pts = mem_get_le32(&raw_header[4]);
93 *pts += ((aom_codec_pts_t)mem_get_le32(&raw_header[8]) << 32);
94 }
95 }
96
97 if (!feof(infile)) {
98 ASAN_UNPOISON_MEMORY_REGION(*buffer, *buffer_size);
99 if (fread(*buffer, 1, frame_size, infile) != frame_size) {
100 warn("Failed to read full frame");
101 return 1;
102 }
103
104 ASAN_POISON_MEMORY_REGION(*buffer + frame_size, *buffer_size - frame_size);
105 *bytes_read = frame_size;
106 return 0;
107 }
108
109 return 1;
110 }
111