Initial version of libomxil-vc4 for RPI3
[platform/adaptation/broadcom/libomxil-vc4.git] / containers / mpgv / mpgv_packetizer.c
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 MPEG1/2 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_time.h"
40 #include "containers/core/containers_utils.h"
41 #include "containers/core/containers_bytestream.h"
42
43 /** Arbitrary number which should be sufficiently high so that no sane frame will
44  * be bigger than that. */
45 #define MAX_FRAME_SIZE (1920*1088*2)
46
47 static uint8_t mpgv_startcode[3] = {0x0, 0x0, 0x1};
48
49 #define PICTURE_CODING_TYPE_I 0x1
50 #define PICTURE_CODING_TYPE_P 0x2
51 #define PICTURE_CODING_TYPE_B 0x3
52
53 VC_CONTAINER_STATUS_T mpgv_packetizer_open( VC_PACKETIZER_T * );
54
55 /*****************************************************************************/
56 typedef struct VC_PACKETIZER_MODULE_T {
57    enum {
58       STATE_SYNC = 0,
59       STATE_SYNC_NEXT,
60       STATE_FRAME_DONE,
61       STATE_UNIT_HEADER,
62       STATE_UNIT_SEQUENCE,
63       STATE_UNIT_GROUP,
64       STATE_UNIT_PICTURE,
65       STATE_UNIT_SLICE,
66       STATE_UNIT_OTHER,
67       STATE_DATA,
68    } state;
69
70    size_t frame_size;
71    size_t unit_offset;
72
73    unsigned int seen_sequence_header;
74    unsigned int seen_picture_header;
75    unsigned int seen_slice;
76    unsigned int lost_sync;
77
78    unsigned int picture_type;
79    unsigned int picture_temporal_ref;
80    int64_t pts;
81    int64_t dts;
82
83    uint32_t bytes_read;
84
85    unsigned int width, height;
86    unsigned int frame_rate_num, frame_rate_den;
87    unsigned int aspect_ratio_num, aspect_ratio_den;
88    bool low_delay;
89
90 } VC_PACKETIZER_MODULE_T;
91
92 /*****************************************************************************/
93 static VC_CONTAINER_STATUS_T mpgv_packetizer_close( VC_PACKETIZER_T *p_ctx )
94 {
95    free(p_ctx->priv->module);
96    return VC_CONTAINER_SUCCESS;
97 }
98
99 /*****************************************************************************/
100 static VC_CONTAINER_STATUS_T mpgv_packetizer_reset( VC_PACKETIZER_T *p_ctx )
101 {
102    VC_PACKETIZER_MODULE_T *module = p_ctx->priv->module;
103    module->lost_sync = 0;
104    module->state = STATE_SYNC;
105    return VC_CONTAINER_SUCCESS;
106 }
107
108 /*****************************************************************************/
109 static VC_CONTAINER_STATUS_T mpgv_read_sequence_header(VC_CONTAINER_BYTESTREAM_T *stream,
110    size_t offset, unsigned int *width, unsigned int *height,
111    unsigned int *frame_rate_num, unsigned int *frame_rate_den,
112    unsigned int *aspect_ratio_num, unsigned int *aspect_ratio_den)
113 {
114    static const int frame_rate[16][2] =
115    { {0, 0}, {24000, 1001}, {24, 1}, {25, 1}, {30000, 1001}, {30, 1}, {50, 1},
116      {60000, 1001}, {60, 1},
117      /* Unofficial values */
118      {15, 1001}, /* From Xing */
119      {5, 1001}, {10, 1001}, {12, 1001}, {15, 1001} /* From libmpeg3 */ };
120    static const int aspect_ratio[16][2] =
121    { {0, 0}, {1, 1}, {4, 3}, {16, 9}, {221, 100} };
122
123    VC_CONTAINER_STATUS_T status;
124    unsigned int w, h, fr, ar;
125    int64_t ar_num, ar_den, div;
126    uint8_t header[8];
127
128    status = bytestream_peek_at( stream, offset, header, sizeof(header));
129    if(status != VC_CONTAINER_SUCCESS)
130       return status;
131
132    w = (header[4] << 4) | (header[5] >> 4);
133    h = ((header[5]&0x0f) << 8) | header[6];
134    ar = header[7] >> 4;
135    fr = header[7]&0x0f;
136    if (!w || !h || !ar || !fr)
137       return VC_CONTAINER_ERROR_CORRUPTED;
138
139    *width = w;
140    *height = h;
141    *frame_rate_num = frame_rate[fr][0];
142    *frame_rate_den = frame_rate[fr][1];
143    ar_num = (int64_t)aspect_ratio[ar][0] * h;
144    ar_den = (int64_t)aspect_ratio[ar][1] * w;
145    div = vc_container_maths_gcd(ar_num, ar_den);
146    if (div)
147    {
148       ar_num /= div;
149       ar_den /= div;
150    }
151    *aspect_ratio_num = ar_num;
152    *aspect_ratio_den = ar_den;
153
154    return VC_CONTAINER_SUCCESS;
155 }
156
157 /*****************************************************************************/
158 static VC_CONTAINER_STATUS_T mpgv_read_picture_header(VC_CONTAINER_BYTESTREAM_T *stream,
159    size_t offset, unsigned int *type, unsigned int *temporal_ref)
160 {
161    VC_CONTAINER_STATUS_T status;
162    uint8_t h[2];
163
164    status = bytestream_peek_at(stream, offset + sizeof(mpgv_startcode) + 1, h, sizeof(h));
165    if(status != VC_CONTAINER_SUCCESS)
166       return status;
167
168    *temporal_ref = (h[0] << 2) | (h[1] >> 6);
169    *type = (h[1] >> 3) & 0x7;
170    return VC_CONTAINER_SUCCESS;
171 }
172
173 /*****************************************************************************/
174 static VC_CONTAINER_STATUS_T mpgv_update_format( VC_PACKETIZER_T *p_ctx )
175 {
176    VC_PACKETIZER_MODULE_T *module = p_ctx->priv->module;
177
178    LOG_DEBUG(0, "mpgv format: width %i, height %i, rate %i/%i, ar %i/%i",
179              module->width, module->height, module->frame_rate_num, module->frame_rate_den,
180              module->aspect_ratio_num, module->aspect_ratio_den);
181
182    p_ctx->out->type->video.width = p_ctx->out->type->video.visible_width = module->width;
183    p_ctx->out->type->video.height = p_ctx->out->type->video.visible_height = module->height;
184    p_ctx->out->type->video.par_num = module->aspect_ratio_num;
185    p_ctx->out->type->video.par_den = module->aspect_ratio_den;
186    p_ctx->out->type->video.frame_rate_num = module->frame_rate_num;
187    p_ctx->out->type->video.frame_rate_den = module->frame_rate_den;
188    return VC_CONTAINER_SUCCESS;
189 }
190
191 /*****************************************************************************/
192 static VC_CONTAINER_STATUS_T mpgv_packetizer_packetize( VC_PACKETIZER_T *p_ctx,
193    VC_CONTAINER_PACKET_T *out, VC_PACKETIZER_FLAGS_T flags)
194 {
195    VC_PACKETIZER_MODULE_T *module = p_ctx->priv->module;
196    VC_CONTAINER_BYTESTREAM_T *stream = &p_ctx->priv->stream;
197    VC_CONTAINER_TIME_T *time = &p_ctx->priv->time;
198    VC_CONTAINER_STATUS_T status;
199    uint8_t header[4];
200    size_t offset;
201
202    while(1) switch (module->state)
203    {
204    case STATE_SYNC:
205       offset = 0;
206       status = bytestream_find_startcode( stream, &offset,
207          mpgv_startcode, sizeof(mpgv_startcode) );
208
209       if(offset && !module->lost_sync)
210          LOG_DEBUG(0, "lost sync");
211
212       bytestream_skip(stream, offset);
213       module->lost_sync += offset;
214
215       if(status != VC_CONTAINER_SUCCESS)
216          return VC_CONTAINER_ERROR_INCOMPLETE_DATA; /* We need more data */
217
218       if(module->lost_sync)
219          LOG_DEBUG(0, "recovered sync after %i bytes", module->lost_sync);
220       module->lost_sync = 0;
221       module->state = STATE_UNIT_HEADER;
222       module->frame_size = 0;
223       module->unit_offset = 0;
224       /* fall through to the next state */
225
226    case STATE_UNIT_HEADER:
227       status = bytestream_peek_at( stream, module->unit_offset, header, sizeof(header));
228       if(status != VC_CONTAINER_SUCCESS)
229       {
230          if (!(flags & VC_PACKETIZER_FLAG_FLUSH) ||
231              !module->seen_picture_header || !module->seen_slice)
232             return VC_CONTAINER_ERROR_INCOMPLETE_DATA;
233          module->state = STATE_FRAME_DONE;
234          break;
235       }
236
237 #if defined(ENABLE_CONTAINERS_LOG_FORMAT_VERBOSE)
238       LOG_DEBUG(0, "found unit (%x)", header[3]);
239 #endif
240
241       /* Detect start of new frame */
242       if(module->seen_picture_header && module->seen_slice &&
243          (header[3] == 0x00 /* A picture header */ ||
244           (header[3] > 0xAF && header[3] != 0xB7) /* Not a slice or sequence end */))
245       {
246          module->state = STATE_FRAME_DONE;
247          break;
248       }
249
250       module->frame_size += sizeof(mpgv_startcode);
251       module->state = STATE_SYNC_NEXT;
252       /* fall through to the next state */
253
254    case STATE_SYNC_NEXT:
255       status = bytestream_find_startcode( stream, &module->frame_size,
256          mpgv_startcode, sizeof(mpgv_startcode) );
257
258       /* Sanity check the size of frames. This makes sure we don't endlessly accumulate data
259        * to make up a new frame. */
260       if(module->frame_size > p_ctx->max_frame_size)
261       {
262          LOG_ERROR(0, "frame too big (%i/%i), dropping", module->frame_size, p_ctx->max_frame_size);
263          bytestream_skip(stream, module->frame_size);
264          module->state = STATE_SYNC;
265          break;
266       }
267       if(status != VC_CONTAINER_SUCCESS)
268       {
269          if (!(flags & VC_PACKETIZER_FLAG_FLUSH) ||
270              !module->seen_picture_header || !module->seen_slice)
271             return VC_CONTAINER_ERROR_INCOMPLETE_DATA;
272          module->state = STATE_FRAME_DONE;
273          break;
274       }
275
276       bytestream_peek_at( stream, module->unit_offset, header, sizeof(header));
277
278       /* Drop everything until we've seen a sequence header */
279       if(header[3] != 0xB3 && !module->seen_sequence_header)
280       {
281          LOG_DEBUG(0, "waiting for sequence header, dropping %i bytes", module->frame_size);
282          module->state = STATE_UNIT_HEADER;
283          bytestream_skip(stream, module->frame_size);
284          module->unit_offset = module->frame_size = 0;
285          break;
286       }
287
288       if(header[3] == 0x00)
289          module->state = STATE_UNIT_PICTURE;
290       else if(header[3] >= 0x01 && header[3] <= 0xAF)
291          module->state = STATE_UNIT_SLICE;
292       else if(header[3] == 0xB3)
293          module->state = STATE_UNIT_SEQUENCE;
294       else if(header[3] == 0xB8)
295          module->state = STATE_UNIT_GROUP;
296       else
297          module->state = STATE_UNIT_OTHER;
298       break;
299
300    case STATE_UNIT_SEQUENCE:
301       status = mpgv_read_sequence_header(stream, module->unit_offset, &module->width, &module->height,
302          &module->frame_rate_num, &module->frame_rate_den, &module->aspect_ratio_num, &module->aspect_ratio_den);
303       if(status != VC_CONTAINER_SUCCESS && !module->seen_sequence_header)
304       {
305          /* We need a sequence header so drop everything until we see one */
306          LOG_DEBUG(0, "invalid first sequence header, dropping %i bytes", module->frame_size);
307          bytestream_skip(stream, module->frame_size);
308          module->state = STATE_SYNC;
309          break;
310       }
311       mpgv_update_format(p_ctx);
312       module->seen_sequence_header = true;
313       vc_container_time_set_samplerate(time, module->frame_rate_num, module->frame_rate_den);
314       module->state = STATE_UNIT_HEADER;
315       module->unit_offset = module->frame_size;
316       break;
317
318    case STATE_UNIT_PICTURE:
319       status = mpgv_read_picture_header(stream, module->unit_offset, &module->picture_type, &module->picture_temporal_ref);
320       if(status != VC_CONTAINER_SUCCESS)
321          return VC_CONTAINER_ERROR_INCOMPLETE_DATA;
322       module->seen_picture_header = true;
323       module->state = STATE_UNIT_HEADER;
324       module->unit_offset = module->frame_size;
325       break;
326
327    case STATE_UNIT_SLICE:
328       module->seen_slice = true;
329       module->state = STATE_UNIT_HEADER;
330       module->unit_offset = module->frame_size;
331       break;
332
333    case STATE_UNIT_GROUP:
334    case STATE_UNIT_OTHER:
335       module->state = STATE_UNIT_HEADER;
336       module->unit_offset = module->frame_size;
337       break;
338
339    case STATE_FRAME_DONE:
340       bytestream_get_timestamps(stream, &module->pts, &module->dts, false);
341
342       if(module->picture_type == PICTURE_CODING_TYPE_B || module->low_delay)
343       {
344          if(module->pts == VC_CONTAINER_TIME_UNKNOWN)
345             module->pts = module->dts;
346          if(module->dts == VC_CONTAINER_TIME_UNKNOWN)
347             module->dts = module->pts;
348       }
349       vc_container_time_set(time, module->pts);
350
351       module->bytes_read = 0;
352       module->state = STATE_DATA;
353       module->seen_slice = false;
354       module->seen_picture_header = false;
355
356 #if defined(ENABLE_CONTAINERS_LOG_FORMAT_VERBOSE)
357       LOG_DEBUG(0, "new frame, type %x, size %i, temp_ref %i)", module->picture_type,
358                 module->frame_size, module->picture_temporal_ref);
359 #endif
360       /* fall through to the next state */
361
362    case STATE_DATA:
363       out->size = module->frame_size - module->bytes_read;
364       out->pts = out->dts = VC_CONTAINER_TIME_UNKNOWN;
365       out->flags = VC_CONTAINER_PACKET_FLAG_FRAME_END;
366
367       if(!module->bytes_read)
368       {
369          out->pts = module->pts;
370          out->dts = module->dts;
371          out->flags |= VC_CONTAINER_PACKET_FLAG_FRAME_START;
372       }
373
374       if(flags & VC_PACKETIZER_FLAG_INFO)
375          return VC_CONTAINER_SUCCESS;
376
377       if(flags & VC_PACKETIZER_FLAG_SKIP)
378       {
379          bytestream_skip( stream, out->size );
380       }
381       else
382       {
383          out->size = MIN(out->size, out->buffer_size);
384          bytestream_get( stream, out->data, out->size );
385       }
386       module->bytes_read += out->size;
387
388       if(module->bytes_read == module->frame_size)
389       {
390          vc_container_time_add(time, 1);
391          module->state = STATE_UNIT_HEADER;
392          module->frame_size = 0;
393          module->unit_offset = 0;
394       }
395       else
396          out->flags &= ~VC_CONTAINER_PACKET_FLAG_FRAME_END;
397
398       return VC_CONTAINER_SUCCESS;
399
400    default:
401       break;
402    };
403
404    return VC_CONTAINER_SUCCESS;
405 }
406
407 /*****************************************************************************/
408 VC_CONTAINER_STATUS_T mpgv_packetizer_open( VC_PACKETIZER_T *p_ctx )
409 {
410    VC_PACKETIZER_MODULE_T *module;
411
412    if(p_ctx->in->codec != VC_CONTAINER_CODEC_MP1V &&
413       p_ctx->in->codec != VC_CONTAINER_CODEC_MP2V)
414       return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED;
415
416    p_ctx->priv->module = module = malloc(sizeof(*module));
417    if(!module)
418       return VC_CONTAINER_ERROR_OUT_OF_MEMORY;
419    memset(module, 0, sizeof(*module));
420
421    vc_container_format_copy( p_ctx->out, p_ctx->in, 0);
422    p_ctx->max_frame_size = MAX_FRAME_SIZE;
423    p_ctx->priv->pf_close = mpgv_packetizer_close;
424    p_ctx->priv->pf_packetize = mpgv_packetizer_packetize;
425    p_ctx->priv->pf_reset = mpgv_packetizer_reset;
426    LOG_DEBUG(0, "using mpeg video packetizer");
427    return VC_CONTAINER_SUCCESS;
428 }
429
430 /*****************************************************************************/
431 VC_PACKETIZER_REGISTER(mpgv_packetizer_open,  "mpgv");