xref: /aosp_15_r20/external/libaom/common/ivfdec.c (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
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