WinGui: Fix another instance of the Caliburn vs Json.net sillyness where objects...
[HandBrake.git] / libhb / nal_units.c
blob0589e024c2ad538e4bd7a0721adea14fceaca759
1 /* nal_units.c
3 * Copyright (c) 2003-2015 HandBrake Team
4 * This file is part of the HandBrake source code.
5 * Homepage: <http://handbrake.fr/>.
6 * It may be used under the terms of the GNU General Public License v2.
7 * For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html
8 */
10 #include <stdint.h>
11 #include <string.h>
13 #include "common.h"
14 #include "nal_units.h"
16 static const uint8_t hb_annexb_startcode[] = { 0x00, 0x00, 0x00, 0x01, };
18 size_t hb_nal_unit_write_annexb(uint8_t *buf,
19 const uint8_t *nal_unit,
20 const size_t nal_unit_size)
22 if (buf != NULL)
24 memcpy(buf, hb_annexb_startcode, sizeof(hb_annexb_startcode));
25 memcpy(buf + sizeof(hb_annexb_startcode), nal_unit, nal_unit_size);
28 return sizeof(hb_annexb_startcode) + nal_unit_size;
31 size_t hb_nal_unit_write_isomp4(uint8_t *buf,
32 const uint8_t *nal_unit,
33 const size_t nal_unit_size)
35 int i;
36 uint8_t length[4]; // 4-byte length replaces Annex B start code prefix
38 if (buf != NULL)
40 for (i = 0; i < sizeof(length); i++)
42 length[i] = (nal_unit_size >> (8 * (sizeof(length) - 1 - i))) & 0xff;
45 memcpy(buf, &length[0], sizeof(length));
46 memcpy(buf + sizeof(length), nal_unit, nal_unit_size);
49 return sizeof(length) + nal_unit_size;
52 uint8_t* hb_annexb_find_next_nalu(const uint8_t *start, size_t *size)
54 uint8_t *nal = NULL;
55 uint8_t *buf = (uint8_t*)start;
56 uint8_t *end = (uint8_t*)start + *size;
58 /* Look for an Annex B start code prefix (3-byte sequence == 1) */
59 while (end - buf > 3)
61 if (!buf[0] && !buf[1] && buf[2] == 1)
63 nal = (buf += 3); // NAL unit begins after start code
64 break;
66 buf++;
69 if (nal == NULL)
71 *size = 0;
72 return NULL;
76 * Start code prefix found, look for the next one to determine the size
78 * A 4-byte sequence == 1 is also a start code, so check for a 3-byte
79 * sequence == 0 too (start code emulation prevention will prevent such a
80 * sequence from occurring outside of a start code prefix)
82 while (end - buf > 3)
84 if (!buf[0] && !buf[1] && (!buf[2] || buf[2] == 1))
86 end = buf;
87 break;
89 buf++;
92 *size = end - nal;
93 return nal;
96 hb_buffer_t* hb_nal_bitstream_annexb_to_mp4(const uint8_t *data,
97 const size_t size)
99 hb_buffer_t *out;
100 uint8_t *buf, *end;
101 size_t out_size, buf_size;
103 out_size = 0;
104 buf_size = size;
105 buf = (uint8_t*)data;
106 end = (uint8_t*)data + size;
108 while ((buf = hb_annexb_find_next_nalu(buf, &buf_size)) != NULL)
110 out_size += hb_nal_unit_write_isomp4(NULL, buf, buf_size);
111 buf_size = end - buf;
114 out = hb_buffer_init(out_size);
115 if (out == NULL)
117 hb_error("hb_nal_bitstream_annexb_to_mp4: hb_buffer_init failed");
118 return NULL;
121 out_size = 0;
122 buf_size = size;
123 buf = (uint8_t*)data;
124 end = (uint8_t*)data + size;
126 while ((buf = hb_annexb_find_next_nalu(buf, &buf_size)) != NULL)
128 out_size += hb_nal_unit_write_isomp4(out->data + out_size, buf, buf_size);
129 buf_size = end - buf;
132 return out;
135 static size_t mp4_nal_unit_length(const uint8_t *data,
136 const size_t nal_length_size,
137 size_t *nal_unit_length)
139 uint8_t i;
141 /* In MP4, NAL units are preceded by a 2-4 byte length field */
142 for (i = 0, *nal_unit_length = 0; i < nal_length_size; i++)
144 *nal_unit_length |= data[i] << (8 * (nal_length_size - 1 - i));
147 return nal_length_size;
150 hb_buffer_t* hb_nal_bitstream_mp4_to_annexb(const uint8_t *data,
151 const size_t size,
152 const uint8_t nal_length_size)
154 hb_buffer_t *out;
155 uint8_t *buf, *end;
156 size_t out_size, nal_size;
158 out_size = 0;
159 buf = (uint8_t*)data;
160 end = (uint8_t*)data + size;
162 while (end - buf > nal_length_size)
164 buf += mp4_nal_unit_length(buf, nal_length_size, &nal_size);
165 if (end - buf < nal_size)
167 hb_log("hb_nal_bitstream_mp4_to_annexb: truncated bitstream"
168 " (remaining: %lu, expected: %lu)", end - buf, nal_size);
169 return NULL;
172 out_size += hb_nal_unit_write_annexb(NULL, buf, nal_size);
173 buf += nal_size;
176 out = hb_buffer_init(out_size);
177 if (out == NULL)
179 hb_error("hb_nal_bitstream_mp4_to_annexb: hb_buffer_init failed");
180 return NULL;
183 out_size = 0;
184 buf = (uint8_t*)data;
185 end = (uint8_t*)data + size;
187 while (end - buf > nal_length_size)
189 buf += mp4_nal_unit_length(buf, nal_length_size, &nal_size);
190 out_size += hb_nal_unit_write_annexb(out->data + out_size, buf, nal_size);
191 buf += nal_size;
194 return out;