intel_video_config_parser.cpp revision f2bf393a8489b70700439d4fc0f39647e11c00d8
1/* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
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
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18
19#include "intel_video_config_parser.h"
20#include "intel_m4v_config_parser.h"
21#include "oscl_mem.h"
22
23#include "oscl_dll.h"
24
25#define GetUnalignedWord( pb, w ) \
26            (w) = ((uint16) *(pb + 1) << 8) + *pb;
27
28#define GetUnalignedDword( pb, dw ) \
29            (dw) = ((uint32) *(pb + 3) << 24) + \
30                   ((uint32) *(pb + 2) << 16) + \
31                   ((uint16) *(pb + 1) << 8) + *pb;
32
33#define GetUnalignedWordEx( pb, w )     GetUnalignedWord( pb, w ); (pb) += sizeof(uint16);
34#define GetUnalignedDwordEx( pb, dw )   GetUnalignedDword( pb, dw ); (pb) += sizeof(uint32);
35#define GetUnalignedQwordEx( pb, qw )   GetUnalignedQword( pb, qw ); (pb) += sizeof(uint64);
36
37#define LoadBYTE( b, p )    b = *(uint8 *)p;  p += sizeof( uint8 )
38
39#define LoadWORD( w, p )    GetUnalignedWordEx( p, w )
40#define LoadDWORD( dw, p )  GetUnalignedDwordEx( p, dw )
41#define LoadQWORD( qw, p )  GetUnalignedQwordEx( p, qw )
42
43#ifndef MAKEFOURCC_WMC
44#define MAKEFOURCC_WMC(ch0, ch1, ch2, ch3) \
45        ((uint32)(uint8)(ch0) | ((uint32)(uint8)(ch1) << 8) |   \
46        ((uint32)(uint8)(ch2) << 16) | ((uint32)(uint8)(ch3) << 24 ))
47
48#define mmioFOURCC_WMC(ch0, ch1, ch2, ch3)  MAKEFOURCC_WMC(ch0, ch1, ch2, ch3)
49#endif
50
51#define FOURCC_WMV2     mmioFOURCC_WMC('W','M','V','2')
52#define FOURCC_WMV3     mmioFOURCC_WMC('W','M','V','3')
53#define FOURCC_WMVA     mmioFOURCC_WMC('W','M','V','A')
54#define FOURCC_WVC1     mmioFOURCC_WMC('W','V','C','1')
55//For WMVA
56#define ASFBINDING_SIZE                   1   // size of ASFBINDING is 1 byte
57#define FOURCC_MP42     mmioFOURCC_WMC('M','P','4','2')
58#define FOURCC_MP43     mmioFOURCC_WMC('M','P','4','3')
59#define FOURCC_mp42     mmioFOURCC_WMC('m','p','4','2')
60#define FOURCC_mp43     mmioFOURCC_WMC('m','p','4','3')
61
62
63OSCL_DLL_ENTRY_POINT_DEFAULT()
64
65int32 GetNAL_Config(uint8** bitstream, int32* size);
66
67OSCL_EXPORT_REF int16 intel_video_config_parser(pvVideoConfigParserInputs *aInputs, pvVideoConfigParserOutputs *aOutputs)
68{
69    if (aInputs->iMimeType == PVMF_MIME_M4V) //m4v
70    {
71        mp4StreamType psBits;
72        psBits.data = aInputs->inPtr;
73        if (aInputs->inBytes <= 0)
74        {
75            return -1;
76        }
77        psBits.numBytes = aInputs->inBytes;
78        psBits.bytePos = 0;
79        psBits.bitBuf = 0;
80        psBits.dataBitPos = 0;
81        psBits.bitPos = 32;
82
83        int32 width, height, display_width, display_height = 0;
84        int32 profile_level = 0;
85        int16 retval = 0;
86        retval = iDecodeVOLHeader(&psBits, &width, &height, &display_width, &display_height, &profile_level);
87        if (retval != 0)
88        {
89            return retval;
90        }
91        aOutputs->width  = (uint32)display_width;
92        aOutputs->height = (uint32)display_height;
93        aOutputs->profile = (uint32)profile_level; // for mp4, profile/level info is packed
94        aOutputs->level = 0;
95    }
96    else if (aInputs->iMimeType == PVMF_MIME_H2631998 ||
97             aInputs->iMimeType == PVMF_MIME_H2632000)//h263
98    {
99        // Nothing to do for h263
100        aOutputs->width  = 0;
101        aOutputs->height = 0;
102        aOutputs->profile = 0;
103        aOutputs->level = 0;
104    }
105    else if (aInputs->iMimeType == PVMF_MIME_H264_VIDEO ||
106             aInputs->iMimeType == PVMF_MIME_H264_VIDEO_MP4) //avc
107    {
108        int32 width, height, display_width, display_height = 0;
109        int32 profile_idc, level_idc = 0;
110
111        uint8 *tp = aInputs->inPtr;
112
113        if (aInputs->inBytes > 1)
114        {
115            if (tp[0] == 0 && tp[1] == 0)
116            {
117                // ByteStream Format
118                uint8* tmp_ptr = tp;
119                uint8* buffer_begin = tp;
120                int16 length = 0;
121                int initbufsize = aInputs->inBytes;
122                int tConfigSize = 0;
123                do
124                {
125                    tmp_ptr += length;
126                    length = GetNAL_Config(&tmp_ptr, &initbufsize);
127                    buffer_begin[0] = length & 0xFF;
128                    buffer_begin[1] = (length >> 8) & 0xFF;
129                    oscl_memcpy(buffer_begin + 2, tmp_ptr, length);
130                    buffer_begin += (length + 2);
131                    tConfigSize += (length + 2);
132                }
133                while (initbufsize > 0);
134            }
135        }
136
137        // check codec info and get settings
138        int16 retval;
139        retval = iGetAVCConfigInfo(tp,
140                                   aInputs->inBytes,
141                                   (int*) & width,
142                                   (int*) & height,
143                                   (int*) & display_width,
144                                   (int*) & display_height,
145                                   (int*) & profile_idc,
146                                   (int*) & level_idc);
147        if (retval != 0)
148        {
149            return retval;
150        }
151        aOutputs->width  = (uint32)display_width;
152        aOutputs->height = (uint32)display_height;
153        aOutputs->profile = (uint32)profile_idc;
154        aOutputs->level = (uint32) level_idc;
155    }
156    else if (aInputs->iMimeType == PVMF_MIME_WMV) //wmv
157    {
158        uint32 dwdat;
159        uint16 wdat;
160        uint8 bdat;
161        uint8 *pData = aInputs->inPtr;
162
163        LoadDWORD(dwdat, pData); // Window width
164        LoadDWORD(dwdat, pData); // Window height
165        LoadBYTE(bdat, pData);
166        LoadWORD(wdat, pData);  // Size of image info.
167
168        // BITMAPINFOHEADER
169        LoadDWORD(dwdat, pData); // Size of BMAPINFOHDR
170        LoadDWORD(dwdat, pData);
171        aOutputs->width = dwdat;
172        LoadDWORD(dwdat, pData);
173        aOutputs->height = dwdat;
174
175        /* WMV1 and WMV2 are not supported. Rejected here. */
176        /* Code to Check if comp is WMV1 then return not supported */
177        pData += 4;
178        LoadDWORD(dwdat, pData);
179        uint32 NewCompression = dwdat;
180        uint32 NewSeqHeader = 0;
181        uint32 NewProfile = 0;
182        // in case of WMV store "Compression Type as Level"
183        aOutputs->level = NewCompression;
184
185        if (NewCompression != FOURCC_WMV2 &&
186                NewCompression != FOURCC_WMV3 &&
187                NewCompression != FOURCC_WVC1 &&
188                NewCompression != FOURCC_WMVA &&
189                NewCompression != FOURCC_MP42 &&
190                NewCompression != FOURCC_MP43 &&
191                NewCompression != FOURCC_mp42 &&
192                NewCompression != FOURCC_mp43)
193        {
194            return -1;
195        }
196        // get profile etc.
197        // Check sequence header
198        switch (NewCompression)
199        {
200            case FOURCC_WMV3:
201            {
202                // start fresh
203                pData = aInputs->inPtr;
204                pData += (11 + 40); //sizeof(BITMAPINFOHEADER); // position to sequence header
205
206                LoadDWORD(dwdat, pData);
207                NewSeqHeader = dwdat; // this is little endian read sequence header
208
209                NewProfile = (NewSeqHeader & 0xC0) >> 6; // 0 - simple , 1- main, 3 - complex, 2-forbidden
210
211                break;
212            }
213            case FOURCC_WMVA:
214            {
215                pData = aInputs->inPtr;
216                pData += (11 + 40 + ASFBINDING_SIZE); //sizeof(BITMAPINFOHEADER); // position to sequence header
217
218                LoadDWORD(dwdat, pData); // prefix  // this is little endian read sequence header
219                LoadDWORD(dwdat, pData);
220                NewSeqHeader = dwdat;
221
222                NewProfile = (NewSeqHeader & 0xC0) >> 6; // this must be 3
223            }
224            break;
225
226            default:
227
228                NewProfile = 0;
229                break;
230        }
231
232        aOutputs->profile = NewProfile;
233
234    }
235    else
236    {
237        return -1;
238    }
239    return 0;
240}
241
242
243/* This function finds a nal from the SC's, moves the bitstream pointer to the beginning of the NAL unit, returns the
244    size of the NAL, and at the same time, updates the remaining size in the bitstream buffer that is passed in */
245int32 GetNAL_Config(uint8** bitstream, int32* size)
246{
247    int i = 0;
248    int j;
249    uint8* nal_unit = *bitstream;
250    int count = 0;
251
252    /* find SC at the beginning of the NAL */
253    while (nal_unit[i++] == 0 && i < *size)
254    {
255    }
256
257    if (nal_unit[i-1] == 1)
258    {
259        *bitstream = nal_unit + i;
260    }
261    else
262    {
263        j = *size;
264        *size = 0;
265        return j;  // no SC at the beginning, not supposed to happen
266    }
267
268    j = i;
269
270    /* found the SC at the beginning of the NAL, now find the SC at the beginning of the next NAL */
271    while (i < *size)
272    {
273        if (count == 2 && nal_unit[i] == 0x01)
274        {
275            i -= 2;
276            break;
277        }
278
279        if (nal_unit[i])
280            count = 0;
281        else
282            count++;
283        i++;
284    }
285
286    *size -= i;
287    return (i - j);
288}
289