1 | /* |
2 | Copyright (c) 2012, Broadcom Europe Ltd |
3 | All rights reserved. |
4 | |
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the following conditions are met: |
7 | * Redistributions of source code must retain the above copyright |
8 | notice, this list of conditions and the following disclaimer. |
9 | * Redistributions in binary form must reproduce the above copyright |
10 | notice, this list of conditions and the following disclaimer in the |
11 | documentation and/or other materials provided with the distribution. |
12 | * Neither the name of the copyright holder nor the |
13 | names of its contributors may be used to endorse or promote products |
14 | derived from this software without specific prior written permission. |
15 | |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY |
20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ |
27 | |
28 | /** \file |
29 | * Implementation of an ISO 14496-15 to Annexe-B AVC video packetizer. |
30 | */ |
31 | |
32 | #include <stdlib.h> |
33 | #include <string.h> |
34 | |
35 | #include "containers/packetizers.h" |
36 | #include "containers/core/packetizers_private.h" |
37 | #include "containers/core/containers_common.h" |
38 | #include "containers/core/containers_logging.h" |
39 | #include "containers/core/containers_utils.h" |
40 | #include "containers/core/containers_bytestream.h" |
41 | |
42 | #ifndef ENABLE_CONTAINERS_LOG_FORMAT_VERBOSE |
43 | //#define ENABLE_CONTAINERS_LOG_FORMAT_VERBOSE |
44 | #endif |
45 | |
46 | /** Arbitrary number which should be sufficiently high so that no sane frame will |
47 | * be bigger than that. */ |
48 | #define MAX_FRAME_SIZE (1920*1088*2) |
49 | |
50 | VC_CONTAINER_STATUS_T avc1_packetizer_open( VC_PACKETIZER_T * ); |
51 | |
52 | /*****************************************************************************/ |
53 | typedef struct VC_PACKETIZER_MODULE_T { |
54 | enum { |
55 | STATE_FRAME_WAIT = 0, |
56 | STATE_BUFFER_INIT, |
57 | STATE_NAL_START, |
58 | STATE_NAL_DATA, |
59 | } state; |
60 | |
61 | unsigned int length_size; |
62 | |
63 | unsigned int frame_size; |
64 | unsigned int bytes_read; |
65 | unsigned int start_code_bytes_left; |
66 | unsigned int nal_bytes_left; |
67 | |
68 | } VC_PACKETIZER_MODULE_T; |
69 | |
70 | static const uint8_t h264_start_code[] = {0, 0, 0, 1}; |
71 | |
72 | /*****************************************************************************/ |
73 | static VC_CONTAINER_STATUS_T avc1_packetizer_close( VC_PACKETIZER_T *p_ctx ) |
74 | { |
75 | free(p_ctx->priv->module); |
76 | return VC_CONTAINER_SUCCESS; |
77 | } |
78 | |
79 | /*****************************************************************************/ |
80 | static VC_CONTAINER_STATUS_T avc1_packetizer_reset( VC_PACKETIZER_T *p_ctx ) |
81 | { |
82 | VC_PACKETIZER_MODULE_T *module = p_ctx->priv->module; |
83 | module->state = STATE_FRAME_WAIT; |
84 | module->frame_size = 0; |
85 | module->bytes_read = 0; |
86 | return VC_CONTAINER_SUCCESS; |
87 | } |
88 | |
89 | /*****************************************************************************/ |
90 | static VC_CONTAINER_STATUS_T avc1_packetizer_packetize( VC_PACKETIZER_T *p_ctx, |
91 | VC_CONTAINER_PACKET_T *out, VC_PACKETIZER_FLAGS_T flags) |
92 | { |
93 | VC_PACKETIZER_MODULE_T *module = p_ctx->priv->module; |
94 | VC_CONTAINER_BYTESTREAM_T *stream = &p_ctx->priv->stream; |
95 | VC_CONTAINER_PACKET_T *packet; |
96 | unsigned int offset, size, nal_num; |
97 | uint8_t data[4]; |
98 | VC_CONTAINER_PARAM_UNUSED(nal_num); |
99 | |
100 | while(1) switch (module->state) |
101 | { |
102 | case STATE_FRAME_WAIT: |
103 | for (packet = stream->current, size = 0; |
104 | packet && !(packet->flags & VC_CONTAINER_PACKET_FLAG_FRAME_END); |
105 | packet = packet->next) |
106 | size += packet->size; |
107 | if (!packet) |
108 | return VC_CONTAINER_ERROR_INCOMPLETE_DATA; /* We need more data */ |
109 | |
110 | size += packet->size; |
111 | |
112 | /* We now have a complete frame available */ |
113 | |
114 | module->nal_bytes_left = 0; |
115 | module->start_code_bytes_left = 0; |
116 | |
117 | /* Find out the number of NAL units and size of the frame */ |
118 | for (offset = nal_num = 0; offset + module->length_size < size; nal_num++) |
119 | { |
120 | unsigned int nal_size; |
121 | |
122 | bytestream_peek_at(stream, offset, data, module->length_size); |
123 | offset += module->length_size; |
124 | |
125 | nal_size = data[0]; |
126 | if (module->length_size > 1) |
127 | nal_size = (nal_size << 8)|data[1]; |
128 | if (module->length_size > 2) |
129 | nal_size = (nal_size << 8)|data[2]; |
130 | if (module->length_size > 3) |
131 | nal_size = (nal_size << 8)|data[3]; |
132 | if (offset + nal_size > size) |
133 | nal_size = size - offset; |
134 | |
135 | offset += nal_size; |
136 | module->frame_size += nal_size + sizeof(h264_start_code); |
137 | #ifdef ENABLE_CONTAINERS_LOG_FORMAT_VERBOSE |
138 | LOG_DEBUG(0, "nal unit size %u" , nal_size); |
139 | #endif |
140 | } |
141 | LOG_DEBUG(0, "frame size: %u(%u/%u), pts: %" PRIi64, module->frame_size, |
142 | size, nal_num, stream->current->pts); |
143 | |
144 | /* fall through to the next state */ |
145 | module->state = STATE_BUFFER_INIT; |
146 | |
147 | case STATE_BUFFER_INIT: |
148 | packet = stream->current; |
149 | out->size = module->frame_size - module->bytes_read; |
150 | out->pts = out->dts = VC_CONTAINER_TIME_UNKNOWN; |
151 | out->flags = VC_CONTAINER_PACKET_FLAG_FRAME_END; |
152 | |
153 | if (!module->bytes_read) |
154 | { |
155 | out->pts = packet->pts; |
156 | out->dts = packet->dts; |
157 | out->flags |= VC_CONTAINER_PACKET_FLAG_FRAME_START; |
158 | } |
159 | |
160 | if (flags & VC_PACKETIZER_FLAG_INFO) |
161 | return VC_CONTAINER_SUCCESS; |
162 | |
163 | if (flags & VC_PACKETIZER_FLAG_SKIP) |
164 | { |
165 | /* The easiest is to just drop all the packets belonging to the frame */ |
166 | while (!(stream->current->flags & VC_CONTAINER_PACKET_FLAG_FRAME_END)) |
167 | bytestream_skip_packet(stream); |
168 | bytestream_skip_packet(stream); |
169 | |
170 | module->frame_size = 0; |
171 | module->bytes_read = 0; |
172 | return VC_CONTAINER_SUCCESS; |
173 | } |
174 | |
175 | /* We now know that we'll have to read some data so reset the output size */ |
176 | out->size = 0; |
177 | |
178 | /* Go to the next relevant state */ |
179 | module->state = STATE_NAL_START; |
180 | if (module->nal_bytes_left || module->bytes_read == module->frame_size) |
181 | module->state = STATE_NAL_DATA; |
182 | break; |
183 | |
184 | case STATE_NAL_START: |
185 | /* Extract the size of the current NAL */ |
186 | bytestream_get(stream, data, module->length_size); |
187 | |
188 | module->nal_bytes_left = data[0]; |
189 | if (module->length_size > 1) |
190 | module->nal_bytes_left = (module->nal_bytes_left << 8)|data[1]; |
191 | if (module->length_size > 2) |
192 | module->nal_bytes_left = (module->nal_bytes_left << 8)|data[2]; |
193 | if (module->length_size > 3) |
194 | module->nal_bytes_left = (module->nal_bytes_left << 8)|data[3]; |
195 | |
196 | if (module->bytes_read + module->nal_bytes_left + sizeof(h264_start_code) > |
197 | module->frame_size) |
198 | { |
199 | LOG_ERROR(0, "truncating nal (%u/%u)" , module->nal_bytes_left, |
200 | module->frame_size - module->bytes_read - sizeof(h264_start_code)); |
201 | module->nal_bytes_left = module->frame_size - sizeof(h264_start_code); |
202 | } |
203 | |
204 | #ifdef ENABLE_CONTAINERS_LOG_FORMAT_VERBOSE |
205 | LOG_DEBUG(0, "nal unit size %u" , module->nal_bytes_left); |
206 | #endif |
207 | |
208 | module->start_code_bytes_left = sizeof(h264_start_code); |
209 | |
210 | /* fall through to the next state */ |
211 | module->state = STATE_NAL_DATA; |
212 | |
213 | case STATE_NAL_DATA: |
214 | /* Start by adding the start code */ |
215 | if (module->start_code_bytes_left) |
216 | { |
217 | size = MIN(out->buffer_size - out->size, module->start_code_bytes_left); |
218 | memcpy(out->data + out->size, h264_start_code + sizeof(h264_start_code) - |
219 | module->start_code_bytes_left, size); |
220 | module->start_code_bytes_left -= size; |
221 | module->bytes_read += size; |
222 | out->size += size; |
223 | } |
224 | |
225 | /* Then append the NAL unit itself */ |
226 | if (module->nal_bytes_left) |
227 | { |
228 | size = MIN(out->buffer_size - out->size, module->nal_bytes_left); |
229 | bytestream_get( stream, out->data + out->size, size ); |
230 | module->nal_bytes_left -= size; |
231 | module->bytes_read += size; |
232 | out->size += size; |
233 | } |
234 | |
235 | /* Check whether we're done */ |
236 | if (module->bytes_read == module->frame_size) |
237 | { |
238 | bytestream_skip_packet(stream); |
239 | module->state = STATE_FRAME_WAIT; |
240 | module->frame_size = 0; |
241 | module->bytes_read = 0; |
242 | return VC_CONTAINER_SUCCESS; |
243 | } |
244 | else if (out->buffer_size == out->size) |
245 | { |
246 | out->flags &= ~VC_CONTAINER_PACKET_FLAG_FRAME_END; |
247 | module->state = STATE_BUFFER_INIT; |
248 | return VC_CONTAINER_SUCCESS; |
249 | } |
250 | |
251 | /* We're not done, go to the next relevant state */ |
252 | module->state = STATE_NAL_START; |
253 | break; |
254 | |
255 | default: |
256 | break; |
257 | }; |
258 | |
259 | return VC_CONTAINER_SUCCESS; |
260 | } |
261 | |
262 | /*****************************************************************************/ |
263 | static VC_CONTAINER_STATUS_T avc1_packetizer_codecconfig( VC_PACKETIZER_T *p_ctx ) |
264 | { |
265 | VC_PACKETIZER_MODULE_T *module = p_ctx->priv->module; |
266 | VC_CONTAINER_STATUS_T status; |
267 | uint8_t *out, * = p_ctx->in->extradata + 5; |
268 | uint8_t * = extra + p_ctx->in->extradata_size - 5; |
269 | unsigned int i, j, nal_size, out_size = 0; |
270 | |
271 | if (p_ctx->in->extradata_size <= 5 || |
272 | p_ctx->in->extradata[0] != 1 /* configurationVersion */) |
273 | return VC_CONTAINER_ERROR_FORMAT_INVALID; |
274 | |
275 | status = vc_container_format_extradata_alloc(p_ctx->out, p_ctx->in->extradata_size); |
276 | if (status != VC_CONTAINER_SUCCESS) |
277 | return status; |
278 | |
279 | out = p_ctx->out->extradata; |
280 | module->length_size = (*(p_ctx->in->extradata + 4) & 0x3) + 1; |
281 | |
282 | for (i = 0; i < 2 && extra < extra_end - 1; i++) |
283 | { |
284 | j = *(extra++) & (!i ? 0x1F : 0xFF); |
285 | for (; j > 0 && extra < extra_end - 2; j--) |
286 | { |
287 | nal_size = (extra[0] << 8) | extra[1]; extra += 2; |
288 | if (extra + nal_size > extra_end) |
289 | { |
290 | extra = extra_end; |
291 | break; |
292 | } |
293 | |
294 | out[0] = out[1] = out[2] = 0; out[3] = 1; |
295 | memcpy(out + 4, extra, nal_size); |
296 | out += nal_size + 4; extra += nal_size; |
297 | out_size += nal_size + 4; |
298 | } |
299 | } |
300 | |
301 | p_ctx->out->extradata_size = out_size; |
302 | return VC_CONTAINER_SUCCESS; |
303 | } |
304 | |
305 | /*****************************************************************************/ |
306 | VC_CONTAINER_STATUS_T avc1_packetizer_open( VC_PACKETIZER_T *p_ctx ) |
307 | { |
308 | VC_PACKETIZER_MODULE_T *module; |
309 | VC_CONTAINER_STATUS_T status; |
310 | |
311 | if(p_ctx->in->codec != VC_CONTAINER_CODEC_H264 && |
312 | p_ctx->out->codec != VC_CONTAINER_CODEC_H264) |
313 | return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED; |
314 | if(p_ctx->in->codec_variant != VC_CONTAINER_VARIANT_H264_AVC1 && |
315 | p_ctx->out->codec_variant != VC_CONTAINER_VARIANT_H264_DEFAULT) |
316 | return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED; |
317 | if(!(p_ctx->in->flags & VC_CONTAINER_ES_FORMAT_FLAG_FRAMED)) |
318 | return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED; |
319 | |
320 | p_ctx->priv->module = module = malloc(sizeof(*module)); |
321 | if(!module) |
322 | return VC_CONTAINER_ERROR_OUT_OF_MEMORY; |
323 | memset(module, 0, sizeof(*module)); |
324 | |
325 | vc_container_format_copy(p_ctx->out, p_ctx->in, 0); |
326 | status = avc1_packetizer_codecconfig(p_ctx); |
327 | if (status != VC_CONTAINER_SUCCESS) |
328 | { |
329 | free(module); |
330 | return status; |
331 | } |
332 | |
333 | p_ctx->out->codec_variant = VC_CONTAINER_VARIANT_H264_DEFAULT; |
334 | p_ctx->max_frame_size = MAX_FRAME_SIZE; |
335 | p_ctx->priv->pf_close = avc1_packetizer_close; |
336 | p_ctx->priv->pf_packetize = avc1_packetizer_packetize; |
337 | p_ctx->priv->pf_reset = avc1_packetizer_reset; |
338 | LOG_DEBUG(0, "using avc1 video packetizer" ); |
339 | return VC_CONTAINER_SUCCESS; |
340 | } |
341 | |
342 | /*****************************************************************************/ |
343 | VC_PACKETIZER_REGISTER(avc1_packetizer_open, "avc1" ); |
344 | |