1 /*
2  * Copyright (C) 2009 The Android Open Source Project
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 /*------------------------------------------------------------------------------
18 
19     Table of contents
20 
21      1. Include headers
22      2. External compiler flags
23      3. Module defines
24      4. Local function prototypes
25      5. Functions
26           H264SwDecInit
27           H264SwDecGetInfo
28           H264SwDecRelease
29           H264SwDecDecode
30           H264SwDecGetAPIVersion
31           H264SwDecNextPicture
32 
33 ------------------------------------------------------------------------------*/
34 
35 /*------------------------------------------------------------------------------
36     1. Include headers
37 ------------------------------------------------------------------------------*/
38 #include <stdlib.h>
39 #include <string.h>
40 #include "basetype.h"
41 #include "h264bsd_container.h"
42 #include "H264SwDecApi.h"
43 #include "h264bsd_decoder.h"
44 #include "h264bsd_util.h"
45 
46 #define UNUSED(x) (void)(x)
47 
48 /*------------------------------------------------------------------------------
49        Version Information
50 ------------------------------------------------------------------------------*/
51 
52 #define H264SWDEC_MAJOR_VERSION 2
53 #define H264SWDEC_MINOR_VERSION 3
54 
55 /*------------------------------------------------------------------------------
56     2. External compiler flags
57 --------------------------------------------------------------------------------
58 
59 H264DEC_TRACE           Trace H264 Decoder API function calls.
60 H264DEC_EVALUATION      Compile evaluation version, restricts number of frames
61                         that can be decoded
62 
63 --------------------------------------------------------------------------------
64     3. Module defines
65 ------------------------------------------------------------------------------*/
66 
67 #ifdef H264DEC_TRACE
68 #include <stdio.h>
69 #define DEC_API_TRC(str)    H264SwDecTrace(str)
70 #else
71 #define DEC_API_TRC(str)
72 #endif
73 
74 #ifdef H264DEC_EVALUATION
75 #define H264DEC_EVALUATION_LIMIT   500
76 #endif
77 
H264SwDecTrace(char * string)78 void H264SwDecTrace(char *string) {
79     UNUSED(string);
80 }
81 
H264SwDecMalloc(u32 size)82 void* H264SwDecMalloc(u32 size) {
83     return malloc(size);
84 }
85 
H264SwDecFree(void * ptr)86 void H264SwDecFree(void *ptr) {
87     free(ptr);
88 }
89 
H264SwDecMemcpy(void * dest,void * src,u32 count)90 void H264SwDecMemcpy(void *dest, void *src, u32 count) {
91     memcpy(dest, src, count);
92 }
93 
H264SwDecMemset(void * ptr,i32 value,u32 count)94 void H264SwDecMemset(void *ptr, i32 value, u32 count) {
95     memset(ptr, value, count);
96 }
97 
98 
99 /*------------------------------------------------------------------------------
100 
101     Function: H264SwDecInit()
102 
103         Functional description:
104             Initialize decoder software. Function reserves memory for the
105             decoder instance and calls h264bsdInit to initialize the
106             instance data.
107 
108         Inputs:
109             noOutputReordering  flag to indicate decoder that it doesn't have
110                                 to try to provide output pictures in display
111                                 order, saves memory
112 
113         Outputs:
114             decInst             pointer to initialized instance is stored here
115 
116         Returns:
117             H264SWDEC_OK        successfully initialized the instance
118             H264SWDEC_INITFAIL  initialization failed
119             H264SWDEC_PARAM_ERR invalid parameters
120             H264SWDEC_MEM_FAIL  memory allocation failed
121 
122 ------------------------------------------------------------------------------*/
123 
H264SwDecInit(H264SwDecInst * decInst,u32 noOutputReordering)124 H264SwDecRet H264SwDecInit(H264SwDecInst *decInst, u32 noOutputReordering)
125 {
126     u32 rv = 0;
127 
128     decContainer_t *pDecCont;
129 
130     DEC_API_TRC("H264SwDecInit#");
131 
132     /* check that right shift on negative numbers is performed signed */
133     /*lint -save -e* following check causes multiple lint messages */
134     if ( ((-1)>>1) != (-1) )
135     {
136         DEC_API_TRC("H264SwDecInit# ERROR: Right shift is not signed");
137         return(H264SWDEC_INITFAIL);
138     }
139     /*lint -restore */
140 
141     if (decInst == NULL)
142     {
143         DEC_API_TRC("H264SwDecInit# ERROR: decInst == NULL");
144         return(H264SWDEC_PARAM_ERR);
145     }
146 
147     pDecCont = (decContainer_t *)H264SwDecMalloc(sizeof(decContainer_t));
148 
149     if (pDecCont == NULL)
150     {
151         DEC_API_TRC("H264SwDecInit# ERROR: Memory allocation failed");
152         return(H264SWDEC_MEMFAIL);
153     }
154 
155 #ifdef H264DEC_TRACE
156     sprintf(pDecCont->str, "H264SwDecInit# decInst %p noOutputReordering %d",
157             (void*)decInst, noOutputReordering);
158     DEC_API_TRC(pDecCont->str);
159 #endif
160 
161     rv = h264bsdInit(&pDecCont->storage, noOutputReordering);
162     if (rv != HANTRO_OK)
163     {
164         H264SwDecRelease(pDecCont);
165         return(H264SWDEC_MEMFAIL);
166     }
167 
168     pDecCont->decStat  = INITIALIZED;
169     pDecCont->picNumber = 0;
170 
171 #ifdef H264DEC_TRACE
172     sprintf(pDecCont->str, "H264SwDecInit# OK: return %p", (void*)pDecCont);
173     DEC_API_TRC(pDecCont->str);
174 #endif
175 
176     *decInst = (decContainer_t *)pDecCont;
177 
178     return(H264SWDEC_OK);
179 
180 }
181 
182 /*------------------------------------------------------------------------------
183 
184     Function: H264SwDecGetInfo()
185 
186         Functional description:
187             This function provides read access to decoder information. This
188             function should not be called before H264SwDecDecode function has
189             indicated that headers are ready.
190 
191         Inputs:
192             decInst     decoder instance
193 
194         Outputs:
195             pDecInfo    pointer to info struct where data is written
196 
197         Returns:
198             H264SWDEC_OK            success
199             H264SWDEC_PARAM_ERR     invalid parameters
200             H264SWDEC_HDRS_NOT_RDY  information not available yet
201 
202 ------------------------------------------------------------------------------*/
203 
H264SwDecGetInfo(H264SwDecInst decInst,H264SwDecInfo * pDecInfo)204 H264SwDecRet H264SwDecGetInfo(H264SwDecInst decInst, H264SwDecInfo *pDecInfo)
205 {
206 
207     storage_t *pStorage;
208 
209     DEC_API_TRC("H264SwDecGetInfo#");
210 
211     if (decInst == NULL || pDecInfo == NULL)
212     {
213         DEC_API_TRC("H264SwDecGetInfo# ERROR: decInst or pDecInfo is NULL");
214         return(H264SWDEC_PARAM_ERR);
215     }
216 
217     pStorage = &(((decContainer_t *)decInst)->storage);
218 
219     if (pStorage->activeSps == NULL || pStorage->activePps == NULL)
220     {
221         DEC_API_TRC("H264SwDecGetInfo# ERROR: Headers not decoded yet");
222         return(H264SWDEC_HDRS_NOT_RDY);
223     }
224 
225 #ifdef H264DEC_TRACE
226     sprintf(((decContainer_t*)decInst)->str,
227         "H264SwDecGetInfo# decInst %p  pDecInfo %p", decInst, (void*)pDecInfo);
228     DEC_API_TRC(((decContainer_t*)decInst)->str);
229 #endif
230 
231     /* h264bsdPicWidth and -Height return dimensions in macroblock units,
232      * picWidth and -Height in pixels */
233     pDecInfo->picWidth        = h264bsdPicWidth(pStorage) << 4;
234     pDecInfo->picHeight       = h264bsdPicHeight(pStorage) << 4;
235     pDecInfo->videoRange      = h264bsdVideoRange(pStorage);
236     pDecInfo->matrixCoefficients = h264bsdMatrixCoefficients(pStorage);
237 
238     h264bsdCroppingParams(pStorage,
239         &pDecInfo->croppingFlag,
240         &pDecInfo->cropParams.cropLeftOffset,
241         &pDecInfo->cropParams.cropOutWidth,
242         &pDecInfo->cropParams.cropTopOffset,
243         &pDecInfo->cropParams.cropOutHeight);
244 
245     /* sample aspect ratio */
246     h264bsdSampleAspectRatio(pStorage,
247                              &pDecInfo->parWidth,
248                              &pDecInfo->parHeight);
249 
250     /* profile */
251     pDecInfo->profile = h264bsdProfile(pStorage);
252 
253     DEC_API_TRC("H264SwDecGetInfo# OK");
254 
255     return(H264SWDEC_OK);
256 
257 }
258 
259 /*------------------------------------------------------------------------------
260 
261     Function: H264SwDecRelease()
262 
263         Functional description:
264             Release the decoder instance. Function calls h264bsdShutDown to
265             release instance data and frees the memory allocated for the
266             instance.
267 
268         Inputs:
269             decInst     Decoder instance
270 
271         Outputs:
272             none
273 
274         Returns:
275             none
276 
277 ------------------------------------------------------------------------------*/
278 
H264SwDecRelease(H264SwDecInst decInst)279 void H264SwDecRelease(H264SwDecInst decInst)
280 {
281 
282     decContainer_t *pDecCont;
283 
284     DEC_API_TRC("H264SwDecRelease#");
285 
286     if (decInst == NULL)
287     {
288         DEC_API_TRC("H264SwDecRelease# ERROR: decInst == NULL");
289         return;
290     }
291 
292     pDecCont = (decContainer_t*)decInst;
293 
294 #ifdef H264DEC_TRACE
295     sprintf(pDecCont->str, "H264SwDecRelease# decInst %p",decInst);
296     DEC_API_TRC(pDecCont->str);
297 #endif
298 
299     h264bsdShutdown(&pDecCont->storage);
300 
301     H264SwDecFree(pDecCont);
302 
303 }
304 
305 /*------------------------------------------------------------------------------
306 
307     Function: H264SwDecDecode
308 
309         Functional description:
310             Decode stream data. Calls h264bsdDecode to do the actual decoding.
311 
312         Input:
313             decInst     decoder instance
314             pInput      pointer to input struct
315 
316         Outputs:
317             pOutput     pointer to output struct
318 
319         Returns:
320             H264SWDEC_NOT_INITIALIZED   decoder instance not initialized yet
321             H264SWDEC_PARAM_ERR         invalid parameters
322 
323             H264SWDEC_STRM_PROCESSED    stream buffer decoded
324             H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY   headers decoded,
325                                                 stream buffer not finished
326             H264SWDEC_PIC_RDY                   decoding of a picture finished
327             H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY    decoding of a picture finished,
328                                                 stream buffer not finished
329             H264SWDEC_STRM_ERR                  serious error in decoding, no
330                                                 valid parameter sets available
331                                                 to decode picture data
332             H264SWDEC_EVALUATION_LIMIT_EXCEEDED this can only occur when
333                                                 evaluation version is used,
334                                                 max number of frames reached
335 
336 ------------------------------------------------------------------------------*/
337 
H264SwDecDecode(H264SwDecInst decInst,H264SwDecInput * pInput,H264SwDecOutput * pOutput)338 H264SwDecRet H264SwDecDecode(H264SwDecInst decInst, H264SwDecInput *pInput,
339                   H264SwDecOutput *pOutput)
340 {
341 
342     decContainer_t *pDecCont;
343     u32 strmLen;
344     u32 numReadBytes;
345     u8 *tmpStream;
346     u32 decResult = 0;
347     H264SwDecRet returnValue = H264SWDEC_STRM_PROCESSED;
348 
349     DEC_API_TRC("H264SwDecDecode#");
350 
351     /* Check that function input parameters are valid */
352     if (pInput == NULL || pOutput == NULL)
353     {
354         DEC_API_TRC("H264SwDecDecode# ERROR: pInput or pOutput is NULL");
355         return(H264SWDEC_PARAM_ERR);
356     }
357 
358     if ((pInput->pStream == NULL) || (pInput->dataLen == 0))
359     {
360         DEC_API_TRC("H264SwDecDecode# ERROR: Invalid input parameters");
361         return(H264SWDEC_PARAM_ERR);
362     }
363 
364     pDecCont = (decContainer_t *)decInst;
365 
366     /* Check if decoder is in an incorrect mode */
367     if (decInst == NULL || pDecCont->decStat == UNINITIALIZED)
368     {
369         DEC_API_TRC("H264SwDecDecode# ERROR: Decoder not initialized");
370         return(H264SWDEC_NOT_INITIALIZED);
371     }
372 
373 #ifdef H264DEC_EVALUATION
374     if (pDecCont->picNumber >= H264DEC_EVALUATION_LIMIT)
375         return(H264SWDEC_EVALUATION_LIMIT_EXCEEDED);
376 #endif
377 
378 #ifdef H264DEC_TRACE
379     sprintf(pDecCont->str, "H264SwDecDecode# decInst %p  pInput %p  pOutput %p",
380             decInst, (void*)pInput, (void*)pOutput);
381     DEC_API_TRC(pDecCont->str);
382 #endif
383 
384     pOutput->pStrmCurrPos   = NULL;
385 
386     numReadBytes = 0;
387     strmLen = pInput->dataLen;
388     tmpStream = pInput->pStream;
389     pDecCont->storage.intraConcealmentFlag = pInput->intraConcealmentMethod;
390 
391     do
392     {
393         /* Return HDRS_RDY after DPB flush caused by new SPS */
394         if (pDecCont->decStat == NEW_HEADERS)
395         {
396             decResult = H264BSD_HDRS_RDY;
397             pDecCont->decStat = INITIALIZED;
398         }
399         else /* Continue decoding normally */
400         {
401             decResult = h264bsdDecode(&pDecCont->storage, tmpStream, strmLen,
402                 pInput->picId, &numReadBytes);
403         }
404         tmpStream += numReadBytes;
405         /* check if too many bytes are read from stream */
406         if ( (i32)(strmLen - numReadBytes) >= 0 )
407             strmLen -= numReadBytes;
408         else
409             strmLen = 0;
410 
411         pOutput->pStrmCurrPos = tmpStream;
412 
413         switch (decResult)
414         {
415             case H264BSD_HDRS_RDY:
416 
417                 if(pDecCont->storage.dpb->flushed &&
418                    pDecCont->storage.dpb->numOut !=
419                    pDecCont->storage.dpb->outIndex)
420                 {
421                     /* output first all DPB stored pictures
422                      * DPB flush caused by new SPS */
423                     pDecCont->storage.dpb->flushed = 0;
424                     pDecCont->decStat = NEW_HEADERS;
425                     returnValue = H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY;
426                     strmLen = 0;
427                 }
428                 else
429                 {
430                     returnValue = H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY;
431                     strmLen = 0;
432                 }
433                 break;
434 
435             case H264BSD_PIC_RDY:
436                 pDecCont->picNumber++;
437 
438                 if (strmLen == 0)
439                     returnValue = H264SWDEC_PIC_RDY;
440                 else
441                     returnValue = H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY;
442 
443                 strmLen = 0;
444                 break;
445 
446             case H264BSD_PARAM_SET_ERROR:
447                 if ( !h264bsdCheckValidParamSets(&pDecCont->storage) &&
448                      strmLen == 0 )
449                 {
450                     returnValue = H264SWDEC_STRM_ERR;
451                 }
452                 break;
453             case H264BSD_MEMALLOC_ERROR:
454                 {
455                     returnValue = H264SWDEC_MEMFAIL;
456                     strmLen = 0;
457                 }
458                 break;
459             default:
460                 break;
461         }
462 
463     } while (strmLen);
464 
465 #ifdef H264DEC_TRACE
466     sprintf(pDecCont->str, "H264SwDecDecode# OK: DecResult %d",
467             returnValue);
468     DEC_API_TRC(pDecCont->str);
469 #endif
470 
471     return(returnValue);
472 
473 }
474 
475 /*------------------------------------------------------------------------------
476 
477     Function: H264SwDecGetAPIVersion
478 
479         Functional description:
480             Return version information of the API
481 
482         Inputs:
483             none
484 
485         Outputs:
486             none
487 
488         Returns:
489             API version
490 
491 ------------------------------------------------------------------------------*/
492 
H264SwDecGetAPIVersion()493 H264SwDecApiVersion H264SwDecGetAPIVersion()
494 {
495     H264SwDecApiVersion ver;
496 
497     ver.major = H264SWDEC_MAJOR_VERSION;
498     ver.minor = H264SWDEC_MINOR_VERSION;
499 
500     return(ver);
501 }
502 
503 /*------------------------------------------------------------------------------
504 
505     Function: H264SwDecNextPicture
506 
507         Functional description:
508             Get next picture in display order if any available.
509 
510         Input:
511             decInst     decoder instance.
512             flushBuffer force output of all buffered pictures
513 
514         Output:
515             pOutput     pointer to output structure
516 
517         Returns:
518             H264SWDEC_OK            no pictures available for display
519             H264SWDEC_PIC_RDY       picture available for display
520             H264SWDEC_PARAM_ERR     invalid parameters
521 
522 ------------------------------------------------------------------------------*/
523 
H264SwDecNextPicture(H264SwDecInst decInst,H264SwDecPicture * pOutput,u32 flushBuffer)524 H264SwDecRet H264SwDecNextPicture(H264SwDecInst decInst,
525     H264SwDecPicture *pOutput, u32 flushBuffer)
526 {
527 
528     decContainer_t *pDecCont;
529     u32 numErrMbs, isIdrPic, picId;
530     u32 *pOutPic;
531 
532     DEC_API_TRC("H264SwDecNextPicture#");
533 
534     if (decInst == NULL || pOutput == NULL)
535     {
536         DEC_API_TRC("H264SwDecNextPicture# ERROR: decInst or pOutput is NULL");
537         return(H264SWDEC_PARAM_ERR);
538     }
539 
540     pDecCont = (decContainer_t*)decInst;
541 
542 #ifdef H264DEC_TRACE
543     sprintf(pDecCont->str, "H264SwDecNextPicture# decInst %p pOutput %p %s %d",
544             decInst, (void*)pOutput, "flushBuffer", flushBuffer);
545     DEC_API_TRC(pDecCont->str);
546 #endif
547 
548     if (flushBuffer)
549         h264bsdFlushBuffer(&pDecCont->storage);
550 
551     pOutPic = (u32*)h264bsdNextOutputPicture(&pDecCont->storage, &picId,
552                                              &isIdrPic, &numErrMbs);
553 
554     if (pOutPic == NULL)
555     {
556         DEC_API_TRC("H264SwDecNextPicture# OK: return H264SWDEC_OK");
557         return(H264SWDEC_OK);
558     }
559     else
560     {
561         pOutput->pOutputPicture = pOutPic;
562         pOutput->picId          = picId;
563         pOutput->isIdrPicture   = isIdrPic;
564         pOutput->nbrOfErrMBs    = numErrMbs;
565         DEC_API_TRC("H264SwDecNextPicture# OK: return H264SWDEC_PIC_RDY");
566         return(H264SWDEC_PIC_RDY);
567     }
568 
569 }
570 
571 
572