Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (c) 2010, Texas Instruments Incorporated
      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
      7  * are met:
      8  *
      9  * *  Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  *
     12  * *  Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * *  Neither the name of Texas Instruments Incorporated nor the names of
     17  *    its contributors may be used to endorse or promote products derived
     18  *    from this software without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 /*==============================================================
     34  *! Revision History
     35  *! ============================
     36  *! 21-Oct-2011 Rajesh vandanapu sarthav (at) ti.com: Initial Version
     37  *================================================================*/
     38 
     39 /******************************************************************
     40  *   INCLUDE FILES
     41  ******************************************************************/
     42 #include <stdio.h>
     43 #include <string.h>
     44 #include <assert.h>
     45 #include "omx_proxy_common.h"
     46 #include <timm_osal_interfaces.h>
     47 #include "OMX_TI_IVCommon.h"
     48 #include "OMX_TI_Video.h"
     49 #include "OMX_TI_Index.h"
     50 
     51 #ifdef ENABLE_RAW_BUFFERS_DUMP_UTILITY
     52 #define LOG_TAG "OMXPROXYVIDEODEC"
     53 #include <fcntl.h>
     54 #include <cutils/properties.h>
     55 #include <utils/Log.h>
     56 #include <stdlib.h>
     57 #include <errno.h>
     58 #endif
     59 
     60 #define COMPONENT_NAME "OMX.TI.DUCATI1.VIDEO.DECODER"
     61 /* needs to be specific for every configuration wrapper */
     62 
     63 /* DEFINITIONS for parsing the config information & sequence header for WMV*/
     64 #define VIDDEC_GetUnalignedDword( pb, dw ) \
     65     (dw) = ((OMX_U32) *(pb + 3) << 24) + \
     66         ((OMX_U32) *(pb + 2) << 16) + \
     67         ((OMX_U16) *(pb + 1) << 8) + *pb;
     68 
     69 #define VIDDEC_GetUnalignedDwordEx( pb, dw )   VIDDEC_GetUnalignedDword( pb, dw ); (pb) += sizeof(OMX_U32);
     70 #define VIDDEC_LoadDWORD( dw, p )  VIDDEC_GetUnalignedDwordEx( p, dw )
     71 #define VIDDEC_MAKEFOURCC(ch0, ch1, ch2, ch3) \
     72     ((OMX_U32)(OMX_U8)(ch0) | ((OMX_U32)(OMX_U8)(ch1) << 8) |   \
     73     ((OMX_U32)(OMX_U8)(ch2) << 16) | ((OMX_U32)(OMX_U8)(ch3) << 24 ))
     74 
     75 #define VIDDEC_FOURCC(ch0, ch1, ch2, ch3)  VIDDEC_MAKEFOURCC(ch0, ch1, ch2, ch3)
     76 
     77 #define FOURCC_WMV3     VIDDEC_FOURCC('W','M','V','3')
     78 #define FOURCC_WMV2     VIDDEC_FOURCC('W','M','V','2')
     79 #define FOURCC_WMV1     VIDDEC_FOURCC('W','M','V','1')
     80 #define FOURCC_WVC1     VIDDEC_FOURCC('W','V','C','1')
     81 
     82 #define CSD_POSITION    51 /*Codec Specific Data position on the "stream propierties object"(ASF spec)*/
     83 
     84 typedef struct VIDDEC_WMV_RCV_struct {
     85     OMX_U32 nNumFrames : 24;
     86     OMX_U32 nFrameType : 8;
     87     OMX_U32 nID : 32;
     88     OMX_U32 nStructData : 32;   //STRUCT_C
     89     OMX_U32 nVertSize;          //STRUCT_A-1
     90     OMX_U32 nHorizSize;         //STRUCT_A-2
     91     OMX_U32 nID2 : 32;
     92     OMX_U32 nSequenceHdr : 32;   //STRUCT_B
     93 } VIDDEC_WMV_RCV_struct;
     94 
     95 typedef struct VIDDEC_WMV_VC1_struct {
     96     OMX_U32 nNumFrames  : 24;
     97     OMX_U32 nFrameType  : 8;
     98     OMX_U32 nID         : 32;
     99     OMX_U32 nStructData : 32;   //STRUCT_C
    100     OMX_U32 nVertSize;          //STRUCT_A-1
    101     OMX_U32 nHorizSize;         //STRUCT_A-2
    102     OMX_U32 nID2        : 32;
    103     OMX_U32 nSequenceHdr : 32;   //STRUCT_B
    104 } VIDDEC_WMV_VC1_struct;
    105 
    106 
    107 OMX_ERRORTYPE PrearrageEmptyThisBuffer(OMX_HANDLETYPE hComponent,
    108     OMX_BUFFERHEADERTYPE * pBufferHdr)
    109 {
    110     OMX_ERRORTYPE eError = OMX_ErrorNone;
    111     PROXY_COMPONENT_PRIVATE *pCompPrv = NULL;
    112     OMX_COMPONENTTYPE *hComp = (OMX_COMPONENTTYPE *) hComponent;
    113     OMX_U8* pBuffer = NULL;
    114     OMX_U8* pData = NULL;
    115     OMX_U32 nValue = 0;
    116     OMX_U32 nWidth = 0;
    117     OMX_U32 nHeight = 0;
    118     OMX_U32 nActualCompression = 0;
    119     OMX_U8* pCSD = NULL;
    120     OMX_U32 nSize_CSD = 0;
    121     DOMX_ENTER("");
    122 
    123     PROXY_assert(pBufferHdr != NULL, OMX_ErrorBadParameter, NULL);
    124 
    125     if (pBufferHdr->nFlags & OMX_BUFFERFLAG_CODECCONFIG){
    126         PROXY_assert(hComp->pComponentPrivate != NULL, OMX_ErrorBadParameter, NULL);
    127 
    128         pCompPrv = (PROXY_COMPONENT_PRIVATE *) hComp->pComponentPrivate;
    129         /* Get component role */
    130         OMX_PARAM_COMPONENTROLETYPE compRole;
    131         compRole.nSize = sizeof(OMX_PARAM_COMPONENTROLETYPE);
    132         compRole.nVersion.s.nVersionMajor = 1;
    133         compRole.nVersion.s.nVersionMinor = 1; //Ducati OMX version
    134         compRole.nVersion.s.nRevision = 0;
    135         compRole.nVersion.s.nStep = 0;
    136 
    137         eError = PROXY_GetParameter(hComp, OMX_IndexParamStandardComponentRole, &compRole);
    138         if(eError != OMX_ErrorNone){
    139             DOMX_ERROR("Error getting OMX_IndexParamStandardComponentRole");
    140         }
    141 
    142         if(!strcmp((char *)(compRole.cRole), "video_decoder.wmv")){
    143             pBuffer = pBufferHdr->pBuffer;
    144 
    145             VIDDEC_WMV_RCV_struct sStructRCV;
    146 
    147             DOMX_DEBUG("nFlags: %x", pBufferHdr->nFlags);
    148 
    149             pData = pBufferHdr->pBuffer + 15; /*Position to Width & Height*/
    150             VIDDEC_LoadDWORD(nValue, pData);
    151             nWidth = nValue;
    152             VIDDEC_LoadDWORD(nValue, pData);
    153             nHeight = nValue;
    154 
    155             pData += 4; /*Position to compression type*/
    156             VIDDEC_LoadDWORD(nValue, pData);
    157             nActualCompression = nValue;
    158 
    159             /*Seting pCSD to proper position*/
    160             pCSD = pBufferHdr->pBuffer;
    161             pCSD += CSD_POSITION;
    162             nSize_CSD = pBufferHdr->nFilledLen - CSD_POSITION;
    163 
    164             if(nActualCompression == FOURCC_WMV3){
    165 
    166                 //From VC-1 spec: Table 265: Sequence Layer Data Structure
    167                 sStructRCV.nNumFrames = 0xFFFFFF; /*Infinite frame number*/
    168                 sStructRCV.nFrameType = 0xc5; /*0x85 is the value given by ASF to rcv converter*/
    169                 sStructRCV.nID = 0x04; /*WMV3*/
    170                 sStructRCV.nStructData = 0x018a3106; /*0x06318a01zero fill 0x018a3106*/
    171                 sStructRCV.nVertSize = nHeight;
    172                 sStructRCV.nHorizSize = nWidth;
    173                 sStructRCV.nID2 = 0x0c; /* Fix value */
    174                 sStructRCV.nSequenceHdr = 0x00002a9f; /* This value is not provided by parser, so giving a value from a video*/
    175 
    176                 DOMX_DEBUG("initial: nStructData: %x", sStructRCV.nStructData);
    177                 DOMX_DEBUG("pCSD = %x", (OMX_U32)*pCSD);
    178 
    179                 sStructRCV.nStructData = (OMX_U32)pCSD[0] << 0  |
    180                     pCSD[1] << 8  |
    181                     pCSD[2] << 16 |
    182                     pCSD[3] << 24;
    183 
    184                 DOMX_DEBUG("FINAL: nStructData: %x", sStructRCV.nStructData);
    185 
    186                 //Copy RCV structure to actual buffer
    187                 assert(pBufferHdr->nFilledLen < pBufferHdr->nAllocLen);
    188                 pBufferHdr->nFilledLen = sizeof(VIDDEC_WMV_RCV_struct);
    189                 TIMM_OSAL_Memcpy(pBufferHdr->pBuffer, (OMX_U8*)(&sStructRCV),
    190                     pBufferHdr->nFilledLen);
    191 
    192             }
    193             else if (nActualCompression == FOURCC_WVC1){
    194                 DOMX_DEBUG("VC-1 Advance Profile prearrange");
    195                 pBufferHdr->nOffset = pBufferHdr->nOffset+52;
    196                 pBufferHdr->nFilledLen= pBufferHdr->nFilledLen-52;
    197             }
    198         }
    199     }
    200 
    201     EXIT:
    202     DOMX_EXIT("eError: %d", eError);
    203 
    204     return PROXY_EmptyThisBuffer(hComponent, pBufferHdr);
    205 }
    206 
    207 #ifdef ENABLE_RAW_BUFFERS_DUMP_UTILITY
    208 /**
    209 * Usage#
    210 * By default this feature is kept disabled to avoid security leaks.
    211 *
    212 * (1) Uncomment the below 2 lines from Android.mk
    213 *     #LOCAL_CFLAGS += -DENABLE_RAW_BUFFERS_DUMP_UTILITY
    214 *     #LOCAL_SHARED_LIBRARIES += libcutils
    215 *     And rebuild the omx proxy common component
    216 *
    217 * (2) Before start playback, make sure that "data" folder has r/w
    218 *   permissions. For this, execute the below
    219 *   mount -o rw,remount -t ext3 /dev/block/mmcblk0p1 /data/
    220 *   chmod 777 /data/
    221 *
    222 * (3) Set the property for number of frames to dump
    223 *  eg: setprop debug.video.dumpframe 10:20
    224 *     would dump frames from 10 to 20.
    225 *
    226 * (4) Pull the frames to PC over adb
    227 *    adb pull /data/frame_10.txt
    228 *
    229 * (5) Analyse on PC tools.
    230 */
    231 
    232 /*
    233 * Method to convert NV12 to YUV420p for PC analysis
    234 */
    235 static void convertNV12ToYuv420(DebugFrame_Dump *frameInfo, void *dst)
    236 {
    237 	int stride = 4096; /* ARM Page size = 4k */
    238 	uint32_t ybuf_offset = frameInfo->frame_yoffset * stride + frameInfo->frame_xoffset;
    239 	uint8_t* p1y = (uint8_t*)frameInfo->y_uv[0] + ybuf_offset;
    240 	uint8_t* p2y = (uint8_t*) dst;
    241 	int i, j, j1;
    242 	int width = frameInfo->frame_width;
    243 	int height = frameInfo->frame_height;
    244 
    245 	LOGD("Coverting NV-12 to YUV420p Width[%d], Height[%d] and Stride[%d] offset[%d]",
    246 	width, height, stride, ybuf_offset);
    247 
    248 	/* copy y-buffer, almost bytewise copy, except for stride jumps.*/
    249 	for(i=0;i<height;i++)
    250 	{
    251 		/* copy whole row of Y pixels. source and desination will point to new row each time.*/
    252 		memcpy(p2y+i*width, p1y+i*stride, width);
    253 	}
    254 
    255 	/** copy uv buffers
    256 	* rearrange from  packed planar [uvuvuv] to planar [uuu][vvvv] packages pixel wise
    257 	* calculate the offset for UV buffer
    258 	*/
    259 	uint32_t UV_offset = frameInfo->frame_xoffset +
    260                              (frameInfo->frame_yoffset * stride)/2;
    261 
    262 	const uint8_t* p1uv = (uint8_t*)frameInfo->y_uv[1] + UV_offset;
    263 
    264 	uint8_t* p2u = ((uint8_t*) dst + (width * height));
    265 	uint8_t* p2v = ((uint8_t*) p2u + ((width/2) * (height/2)));
    266 	for(i=0;(i < height/2);i++)
    267 	{
    268 		for(j=0,j1=0;(j< width/2);j++,j1+=2)
    269 		{
    270 			p2u[j] = p1uv[j1];
    271 			p2v[j] = p1uv[j1+1];
    272 		}
    273 		p1uv+=stride;
    274 		p2u+=width/2;
    275 		p2v+=width/2;
    276 	}
    277 }
    278 
    279 void DumpVideoFrame(DebugFrame_Dump *frameInfo)
    280 {
    281 	/* First convert the frame to 420p and then write to SD Card */
    282 	OMX_U32 framesize = (frameInfo->frame_width *
    283                              frameInfo->frame_height * 3) / 2;
    284 	OMX_U8* localbuffer = malloc(framesize);
    285 	if (localbuffer == NULL)
    286 	{
    287 		LOGE("NO HEAP");
    288 		goto EXIT;
    289 	}
    290 	convertNV12ToYuv420(frameInfo, localbuffer);
    291 	int filedes = -1;
    292 	char framenumber[100];
    293 	sprintf(framenumber, "/data/frame_%ld.txt", frameInfo->runningFrame);
    294 	LOGD("file path %s",framenumber);
    295 	filedes = open(framenumber, O_CREAT | O_WRONLY | O_SYNC | O_TRUNC, 0777);
    296 	if(filedes < 0)
    297 	{
    298 		LOGE("\n!!!!!!!!!Error in file open!!!!!!!! [%d][%s]\n", filedes, strerror(errno));
    299 		goto EXIT;
    300 	}
    301 	int ret = write (filedes, (void*)localbuffer, framesize);
    302 	if (ret < (int)framesize)
    303 	{
    304 		LOGE("File Write Failed");
    305 	}
    306 EXIT:
    307 	if (localbuffer)
    308 	{
    309 		free(localbuffer);
    310 		localbuffer = NULL;
    311 	}
    312 	if (filedes > 0)
    313 	{
    314 		close(filedes);
    315 	}
    316 }
    317 
    318 #endif
    319