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