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