373da79f2d567b81cf56531730022c0bfce85b28
[platform/core/api/mediacodec.git] / src / media_codec_bitstream.c
1 /*
2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15  *
16  */
17 #include <stdio.h>
18 #include <dlog.h>
19 #include <media_codec_bitstream.h>
20 #include <gst/base/gstbytereader.h>
21 #include <gst/base/gstbitreader.h>
22
23 void mc_init_bits(mc_bitstream_t *stream, unsigned char *data, int size)
24 {
25         stream->data = data;
26         stream->numBytes = size;
27         stream->bitcnt = 32;
28         stream->bytePos = 0;
29         stream->dataBitPos = 0;
30         stream->buffer = 0;
31 }
32
33 short mc_show_bits(mc_bitstream_t *stream, unsigned char nbits, unsigned int *pulOutData)
34 {
35         unsigned char *bits;
36         unsigned int dataBitPos = stream->dataBitPos;
37         unsigned int bitcnt = stream->bitcnt;
38         unsigned int dataBytePos;
39         unsigned int i;
40
41         if (nbits > (32 - bitcnt))  {
42                 dataBytePos = dataBitPos >> 3;
43                 bitcnt = dataBitPos & 7;
44                 if (dataBytePos > stream->numBytes - 4) {
45                         stream->buffer = 0;
46                         for (i = 0; i < stream->numBytes - dataBytePos; i++) {
47                                 stream->buffer |= stream->data[dataBytePos + i];
48                                 stream->buffer <<= 8;
49                         }
50                         stream->buffer <<= 8 * (3 - i);
51                 } else {
52                         bits = &stream->data[dataBytePos];
53                         stream->buffer = (bits[0] << 24) | (bits[1] << 16) | (bits[2] << 8) | bits[3];
54                 }
55                 stream->bitcnt = bitcnt;
56         }
57         bitcnt += nbits;
58
59         *pulOutData = (stream->buffer >> (32 - bitcnt)) & mask[(unsigned short)nbits];
60
61         return 0;
62 }
63
64 short mc_read_bits(mc_bitstream_t *stream, unsigned char nbits, unsigned int *pulOutData)
65 {
66         unsigned char *bits;
67         unsigned int dataBitPos = stream->dataBitPos;
68         unsigned int bitcnt = stream->bitcnt;
69         unsigned int dataBytePos;
70
71         if ((dataBitPos + nbits) > (stream->numBytes << 3)) {
72                 *pulOutData = 0;
73                 return -1;
74         }
75
76         if (nbits > (32 - bitcnt)) {
77                 dataBytePos = dataBitPos >> 3;
78                 bitcnt = dataBitPos & 7;
79                 bits = &stream->data[dataBytePos];
80                 stream->buffer = (bits[0] << 24) | (bits[1] << 16) | (bits[2] << 8) | bits[3];
81         }
82
83
84         stream->dataBitPos += nbits;
85         stream->bitcnt = (unsigned char)(bitcnt + nbits);
86
87
88         *pulOutData = (stream->buffer >> (32 - stream->bitcnt)) & mask[(unsigned short)nbits];
89
90         return 0;
91 }
92
93 short mc_byte_align(mc_bitstream_t *stream)
94 {
95         unsigned char *bits;
96         unsigned int dataBitPos = stream->dataBitPos;
97         unsigned int bitcnt = stream->bitcnt;
98         unsigned int dataBytePos;
99         unsigned int leftBits;
100
101         leftBits = 8 - (dataBitPos & 0x7);
102         if (leftBits == 8) {
103                 if ((dataBitPos + 8) > (unsigned int)(stream->numBytes << 3))
104                         return (-1);
105                 dataBitPos += 8;
106                 bitcnt += 8;
107         } else {
108                 dataBytePos = dataBitPos >> 3;
109                 dataBitPos += leftBits;
110                 bitcnt += leftBits;
111         }
112
113         if (bitcnt > 32) {
114                 dataBytePos = dataBitPos >> 3;
115                 bits = &stream->data[dataBytePos];
116                 stream->buffer = (bits[0] << 24) | (bits[1] << 16) | (bits[2] << 8) | bits[3];
117         }
118
119
120         stream->dataBitPos = dataBitPos;
121         stream->bitcnt = bitcnt;
122
123         return 0;
124 }
125 unsigned int __mc_bytestream_to_nal(unsigned char *data, int size)
126 {
127         unsigned char val, zero_count;
128         unsigned char *pNal = data;
129         int index = 0;
130
131         zero_count = 0;
132
133         val = pNal[index++];
134         while (!val) {
135                 zero_count++;
136                 val = pNal[index++];
137         }
138
139         zero_count = 0;
140
141         while (1) {
142                 if (index >= size)
143                         return (index - 1);
144
145                 val = pNal[index++];
146
147                 if (!val)
148                         zero_count++;
149                 else {
150                         if ((zero_count >= 2) && (val == 1))
151                                 break;
152                         else
153                                 zero_count = 0;
154                 }
155         }
156
157         if (zero_count > 3)
158                 zero_count = 3;
159
160         return (index - zero_count - 1);
161 }
162
163 int __mc_decode_sps(mc_bitstream_t *pstream, int *width, int *height)
164 {
165         int ret = MC_ERROR_NONE;
166         unsigned int tmp = 0;
167
168         int profile_idc = 0;
169
170         mc_read_bits(pstream, 8, &tmp);
171         mc_read_bits(pstream, 1, &tmp);
172         mc_read_bits(pstream, 1, &tmp);
173         mc_read_bits(pstream, 1, &tmp);
174         mc_read_bits(pstream, 5, &tmp);
175         mc_read_bits(pstream, 8, &tmp);
176
177         profile_idc = tmp;
178
179         if (profile_idc > 51)
180                 ret = MC_INVALID_IN_BUF;
181
182         /*TODO parse width, height, etc...*/
183
184         return ret;
185 }
186
187 int __mc_scan_for_h264_start_codes(const guint8 * data, guint size)
188 {
189         GstByteReader br;
190         gst_byte_reader_init(&br, data, size);
191
192         /* NALU not empty, so we can at least expect 1 (even 2) bytes following sc */
193         return gst_byte_reader_masked_scan_uint32(&br, 0xffffff00, 0x00000100, 0, size);
194 }
195
196 int _mc_check_h264_bytestream(unsigned char *nal, int byte_length, bool port, bool *codec_config, bool *sync_flag, bool *slice)
197 {
198         int ret = 0; /* (ret <= 0)==>>error occured;  (ret > 0)==>>codec data size */
199         int stacked_length = 0;
200         int nal_length = 0;
201         unsigned int syntax = 0;
202         unsigned int state = 0;
203         int count = 0;
204         int nal_unit_type = 0;
205         int codec_length = 0;
206
207         mc_bitstream_t pstream;
208
209         nal_unit_type = nal[2] == 1 ? (nal[3] & 0x1F) : (nal[4] & 0x1F);
210
211         if (nal_unit_type == 0x7 || nal_unit_type == 0x8 || nal_unit_type == 0x9) {
212
213                 while (1) {
214                         nal_length = __mc_bytestream_to_nal(nal + stacked_length, byte_length - stacked_length);
215
216                         mc_init_bits(&pstream, nal + stacked_length, byte_length - stacked_length);
217                         mc_read_bits(&pstream, 32, &syntax);
218                         mc_read_bits(&pstream, 8, &syntax);
219
220                         switch (syntax & 0x1F) {
221                         case NAL_SEQUENCE_PARAMETER_SET:
222                                 LOGD("nal_unit_type : SPS");
223                                 if ((ret = __mc_decode_sps(&pstream, NULL, NULL)) != MC_ERROR_NONE)
224                                         return ret;
225                                 state |= MC_EXIST_SPS;
226                                 codec_length += nal_length;
227                                 break;
228                         case NAL_PICTURE_PARAMETER_SET:
229                                 LOGD("nal_unit_type : PPS");
230                                 state |= MC_EXIST_PPS;
231                                 codec_length += nal_length;
232                                 break;
233                         case NAL_SLICE_IDR:
234                                 LOGD("nal_unit_type : IDR");
235                                 state |= MC_EXIST_IDR;
236                                 break;
237                         default:
238                                 state |= MC_EXIST_SLICE;
239                                 LOGD("nal_unit_type : %x", syntax & 0x1F);
240                                 break;
241                         }
242
243                         LOGD("stacked_length : %d, nal_length : %d, byte_length : %d", stacked_length, nal_length, byte_length);
244
245                         stacked_length += nal_length;
246                         count++;
247
248                         LOGD("codec_data length : %d", codec_length);
249
250                         if ((stacked_length >= byte_length) || count > 5)
251                                 break;
252                 }
253         } else if (nal_unit_type == 0x5) {
254                 state |= MC_EXIST_IDR;
255                 LOGD("nal_unit_type is IDR");
256         } else if (nal_unit_type == 0x01 || nal_unit_type == 0x02 || nal_unit_type == 0x03 || nal_unit_type == 0x04) {
257                 state |= MC_EXIST_SLICE;
258                 LOGD("nal_unit_type : %x", nal_unit_type);
259         } else {
260                 LOGD("Non VCL");
261         }
262
263         LOGD("for debug state :%d, %d", state, MC_VALID_FIRST_SLICE);
264
265         /* input port */
266         if (!port && !CHECK_VALID_PACKET(state, MC_VALID_FIRST_SLICE))
267                 return MC_INVALID_IN_BUF;
268
269         /* output port */
270         if (port) {
271                 *codec_config = CHECK_VALID_PACKET(state, MC_VALID_HEADER) ? 1 : 0;
272                 *sync_flag = CHECK_VALID_PACKET(state, MC_EXIST_IDR) ? 1 : 0;
273                 *slice = CHECK_VALID_PACKET(state, MC_EXIST_SLICE) ? 1 : 0;
274         }
275
276         return codec_length;
277 }
278
279 int _mc_check_valid_h263_frame(unsigned char *p, int size)
280 {
281         unsigned char *end = p + size - 3;
282         int count = 0;
283
284         do {
285                 /* Found the start of the frame, now try to find the end */
286                 if ((p[0] == 0x00) && (p[1] == 0x00) && ((p[2]&0xFC) == 0x80))
287                         count++;
288                 p++;
289         } while (count == 1 && p < end);
290
291         if (count != 1)
292                 return MC_INVALID_IN_BUF; /* frame boundary violated */
293
294         return MC_ERROR_NONE;
295 }
296
297 bool _mc_is_voss(unsigned char *buf, int size, int *codec_size)
298 {
299         unsigned char *p = buf;
300         unsigned char *end = p + size - 3;
301         if (size < 4)
302                 return false;
303
304         if (!((p[0] == 0x00) && (p[1] == 0x00) && (p[2] == 0x01) && (p[3] == 0xB0)))
305                 return false;
306
307         if (codec_size) {
308                 for (; p < end ; p++) {
309                         if ((p[0] == 0x00) && (p[1] == 0x00) && (p[2] == 0x01) && (p[3] == 0xB6)) {
310                                 *codec_size = p-buf;
311                                 break;
312                         }
313                 }
314         }
315
316         return true;
317 }
318
319 bool _mc_is_ivop(unsigned char *p, int size, int pos)
320 {
321         if (size < (pos + 5))
322                 return false;
323
324         p = p + pos;
325
326         if ((p[0] == 0x00) && (p[1] == 0x00) && (p[2] == 0x01) && (p[3] == 0xB6)) {
327                 /* VOP_CODING_TYPE (binary)  Coding method
328                 // 00  intra-coded (I)
329                 // 01  predictive-coded (P)
330                 // 10  bidirectionally-predictive-coded (B)
331                 // 11  sprite (S)
332                 */
333                 if ((p[4] & 0xC0) == 0x0)   /*I-VOP */
334                         return true;
335         }
336         return false;
337 }
338
339 bool _mc_is_vop(unsigned char *p, int size, int pos)
340 {
341         if (size < (pos + 4))
342                 return false;
343
344         p = p + pos;
345
346         if ((p[0] == 0x00) && (p[1] == 0x00) && (p[2] == 0x01) && (p[3] == 0xB6))
347                 return true;
348
349         return false;
350 }
351
352 int _mc_check_mpeg4_out_bytestream(unsigned char *buf, int buf_length, bool* need_codec_data, bool *need_sync_flag)
353 {
354         int codec_data_size = 0;
355         g_return_val_if_fail(need_codec_data != NULL, MC_PARAM_ERROR);
356         g_return_val_if_fail(need_sync_flag != NULL, MC_PARAM_ERROR);
357
358         *need_codec_data = FALSE;
359         *need_sync_flag = FALSE;
360
361         if (_mc_is_voss(buf, buf_length, &codec_data_size))
362                 *need_codec_data = TRUE;
363         if (_mc_is_ivop(buf, buf_length, codec_data_size))
364                 *need_sync_flag = TRUE;
365
366         return codec_data_size;
367 }
368
369 bool _mc_check_h263_out_bytestream(unsigned char *p, int buf_length, bool* need_sync_flag)
370 {
371         g_return_val_if_fail(need_sync_flag != NULL, MC_PARAM_ERROR);
372
373         *need_sync_flag = FALSE;
374
375         /* PSC not present */
376         if ((p[0] != 0x00) || (p[1] != 0x00) || ((p[2]&0xFC) != 0x80))
377                 return false;
378
379         /* PTYPE Field, Bit 9: Picture Coding Type, "0" INTRA (I-picture), "1" INTER (P-picture) */
380         if (!(p[4] & 0x2))
381                 *need_sync_flag = TRUE;
382
383         return TRUE;
384 }
385
386 int _mc_get_h264_codecdata_size(guint8 *data, int size)
387 {
388         int offset = 0;
389         int data_size = 0;
390         bool is_bytestream = FALSE;
391
392         if ((offset = __mc_scan_for_h264_start_codes(data, size)) == -1) {
393                 /*Packetized Format*/
394                 is_bytestream = FALSE;
395         } else {
396                 /*Byte-Stream Format*/
397                 is_bytestream = TRUE;
398         }
399
400         if (is_bytestream) {
401                 /*Byte-Stream Format*/
402                 data_size = _mc_check_h264_bytestream(data, size, 0, NULL, NULL, NULL);
403                 if (data_size <= 0) {
404                         LOGE("No valid SPS/PPS ...");
405                         return MC_INVALID_IN_BUF;
406                 }
407                 return data_size;
408         } else {
409                 /*Packetized Format*/
410                 int num_sps = 0, num_pps = 0;
411                 int nalu_size = 0;
412                 int i = 0;
413                 unsigned int state = 0;
414                 GstBitReader br;
415
416                 offset = 0;
417                 /* parse the avcC data */
418                 if (size < 7) { /* when numSPS==0 and numPPS==0, length is 7 bytes */
419                         LOGE("If contains codec_data, size should over 7 bytes ...");
420                         return MC_INVALID_IN_BUF;
421                 }
422                 /* parse the version, this must be 1 */
423                 if (data[0] != 1) {
424                         LOGE("If contains codec_data, first byte must be 1 ...");
425                         return MC_INVALID_IN_BUF;
426                 }
427
428                 num_sps = data[5] & 0x1f;
429                 offset = 6;
430                 for (i = 0; i < num_sps; i++) {
431                         gst_bit_reader_init(&br, data + offset, size - offset);
432                         nalu_size = gst_bit_reader_get_bits_uint32_unchecked(&br, 2 * 8);
433
434                         offset += nalu_size + 2;
435                         state |= MC_EXIST_SPS;
436                 }
437
438                 num_pps = data[offset];
439                 offset++;
440
441                 for (i = 0; i < num_pps; i++) {
442                         gst_bit_reader_init(&br, data + offset, size - offset);
443                         nalu_size = gst_bit_reader_get_bits_uint32_unchecked(&br, 2 * 8);
444
445                         offset += nalu_size + 2;
446                         state |= MC_EXIST_PPS;
447                 }
448
449                 if (CHECK_VALID_PACKET(state, MC_VALID_HEADER)) {
450                         LOGD("Found valid SPS/PPS data...\n");
451                         return offset;
452                 }
453
454                 return MC_INVALID_IN_BUF;
455         }
456
457 }