1 /*
2  * Copyright © 2018, VideoLAN and dav1d authors
3  * Copyright © 2018, Two Orioles, LLC
4  * Copyright © 2019, James Almer <jamrial@gmail.com>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice, this
11  *    list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  *    this list of conditions and the following disclaimer in the documentation
15  *    and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #ifndef DAV1D_INPUT_PARSE_H
30 #define DAV1D_INPUT_PARSE_H
31 
32 #include <limits.h>
33 
34 #include "dav1d/headers.h"
35 
leb128(FILE * const f,size_t * const len)36 static int leb128(FILE *const f, size_t *const len) {
37     uint64_t val = 0;
38     unsigned i = 0, more;
39     do {
40         uint8_t v;
41         if (fread(&v, 1, 1, f) < 1)
42             return -1;
43         more = v & 0x80;
44         val |= ((uint64_t) (v & 0x7F)) << (i * 7);
45         i++;
46     } while (more && i < 8);
47     if (val > UINT_MAX || more)
48         return -1;
49     *len = (size_t) val;
50     return i;
51 }
52 
53 // these functions are based on an implementation from FFmpeg, and relicensed
54 // with author's permission
55 
leb(const uint8_t * ptr,int sz,size_t * const len)56 static int leb(const uint8_t *ptr, int sz, size_t *const len) {
57     uint64_t val = 0;
58     unsigned i = 0, more;
59     do {
60         if (!sz--) return -1;
61         const int v = *ptr++;
62         more = v & 0x80;
63         val |= ((uint64_t) (v & 0x7F)) << (i * 7);
64         i++;
65     } while (more && i < 8);
66     if (val > UINT_MAX || more)
67         return -1;
68     *len = (size_t) val;
69     return i;
70 }
71 
parse_obu_header(const uint8_t * buf,int buf_size,size_t * const obu_size,enum Dav1dObuType * const type,const int allow_implicit_size)72 static inline int parse_obu_header(const uint8_t *buf, int buf_size,
73                                    size_t *const obu_size,
74                                    enum Dav1dObuType *const type,
75                                    const int allow_implicit_size)
76 {
77     int ret, extension_flag, has_size_flag;
78 
79     if (!buf_size)
80         return -1;
81     if (*buf & 0x80) // obu_forbidden_bit
82         return -1;
83 
84     *type = (*buf & 0x78) >> 3;
85     extension_flag = (*buf & 0x4) >> 2;
86     has_size_flag  = (*buf & 0x2) >> 1;
87     // ignore obu_reserved_1bit
88     buf++;
89     buf_size--;
90 
91     if (extension_flag) {
92         buf++;
93         buf_size--;
94         // ignore fields
95     }
96 
97     if (has_size_flag) {
98         ret = leb(buf, buf_size, obu_size);
99         if (ret < 0)
100             return -1;
101         return (int) *obu_size + ret + 1 + extension_flag;
102     } else if (!allow_implicit_size)
103         return -1;
104 
105     *obu_size = buf_size;
106     return buf_size + 1 + extension_flag;
107 }
108 
109 #endif /* DAV1D_INPUT_PARSE_H */
110