1 /* 2 * Copyright (C) 2011 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 * @file M4DECODER_Null.c 19 * @brief Implementation of the Null decoder public interface 20 * @note This file implements a "null" video decoder, i.e. a decoder 21 * that does nothing 22 ************************************************************************* 23 */ 24 #include "NXPSW_CompilerSwitches.h" 25 26 #include "M4OSA_Types.h" 27 #include "M4OSA_Debug.h" 28 #include "M4TOOL_VersionInfo.h" 29 #include "M4DA_Types.h" 30 #include "M4DECODER_Common.h" 31 #include "M4DECODER_Null.h" 32 33 /** 34 ************************************************************************ 35 * NULL Video Decoder version information 36 ************************************************************************ 37 */ 38 /* CHANGE_VERSION_HERE */ 39 #define M4DECODER_NULL_MAJOR 1 40 #define M4DECODER_NULL_MINOR 0 41 #define M4DECODER_NULL_REVISION 0 42 43 /** 44 ************************************************************************ 45 * structure M4_VideoHandler_Context 46 * @brief Defines the internal context of a video decoder instance 47 * @note The context is allocated and freed by the video decoder 48 ************************************************************************ 49 */ 50 typedef struct { 51 void* m_pLibrary; // Core library identifier 52 M4OSA_Int32 m_DecoderId; // Core decoder identifier 53 M4OSA_Int32 m_RendererId; // Core renderer identifier 54 M4_VideoStreamHandler* m_pVideoStreamhandler; // Video stream description 55 M4_AccessUnit* m_pNextAccessUnitToDecode; // Access unit used to 56 // read and decode one frame 57 void* m_pUserData; // Pointer to any user data 58 M4READER_DataInterface* m_pReader; // Reader data interface 59 M4OSA_Bool m_bDoRendering; // Decides if render required 60 M4OSA_Int32 m_structSize; // Size of the structure 61 62 M4DECODER_OutputFilter* m_pVideoFilter; // Color conversion filter 63 M4VIFI_ImagePlane *pDecYuvData; // Pointer to Yuv data plane 64 M4VIFI_ImagePlane *pDecYuvWithEffect; // Pointer to Yuv plane with color effect 65 M4OSA_Bool bYuvWithEffectSet; // Original Yuv data OR Yuv with color effect 66 67 } M4_VideoHandler_Context; 68 69 /***********************************************************************/ 70 /************** M4DECODER_VideoInterface implementation ****************/ 71 /***********************************************************************/ 72 73 /** 74 ************************************************************************ 75 * @brief Creates an instance of the decoder 76 * @note Allocates the context 77 * 78 * @param pContext: (OUT) Context of the decoder 79 * @param pStreamHandler: (IN) Pointer to a video stream description 80 * @param pSrcInterface: (IN) Pointer to the M4READER_DataInterface 81 * structure that must be used by the 82 * decoder to read data from the stream 83 * @param pAccessUnit (IN) Pointer to an access unit 84 * (allocated by the caller) where decoded data 85 * are stored 86 * 87 * @return M4NO_ERROR There is no error 88 * @return M4ERR_STATE State automaton is not applied 89 * @return M4ERR_ALLOC A memory allocation has failed 90 * @return M4ERR_PARAMETER At least one input parameter is not proper 91 ************************************************************************ 92 */ 93 M4OSA_ERR M4DECODER_NULL_create(M4OSA_Context *pContext, 94 M4_StreamHandler *pStreamHandler, 95 M4READER_GlobalInterface *pReaderGlobalInterface, 96 M4READER_DataInterface *pReaderDataInterface, 97 M4_AccessUnit* pAccessUnit, 98 M4OSA_Void* pUserData) { 99 100 M4_VideoHandler_Context* pStreamContext = M4OSA_NULL; 101 102 *pContext = M4OSA_NULL; 103 pStreamContext = (M4_VideoHandler_Context*)M4OSA_32bitAlignedMalloc ( 104 sizeof(M4_VideoHandler_Context), M4DECODER_MPEG4, 105 (M4OSA_Char *)"M4_VideoHandler_Context"); 106 if (pStreamContext == 0) { 107 return M4ERR_ALLOC; 108 } 109 110 pStreamContext->m_structSize = sizeof(M4_VideoHandler_Context); 111 pStreamContext->m_pNextAccessUnitToDecode = M4OSA_NULL; 112 pStreamContext->m_pLibrary = M4OSA_NULL; 113 pStreamContext->m_pVideoStreamhandler = M4OSA_NULL; 114 pStreamContext->m_DecoderId = -1; 115 pStreamContext->m_RendererId = -1; 116 117 pStreamContext->m_pUserData = M4OSA_NULL; 118 pStreamContext->m_bDoRendering = M4OSA_TRUE; 119 pStreamContext->m_pVideoFilter = M4OSA_NULL; 120 pStreamContext->bYuvWithEffectSet = M4OSA_FALSE; 121 122 *pContext=pStreamContext; 123 return M4NO_ERROR; 124 } 125 126 /** 127 ************************************************************************ 128 * @brief Destroy the instance of the decoder 129 * @note After this call the context is invalid 130 * 131 * @param context: (IN) Context of the decoder 132 * 133 * @return M4NO_ERROR There is no error 134 * @return M4ERR_PARAMETER The context is invalid 135 ************************************************************************ 136 */ 137 M4OSA_ERR M4DECODER_NULL_destroy(M4OSA_Context pContext) { 138 139 M4_VideoHandler_Context* pStreamContext = (M4_VideoHandler_Context*)pContext; 140 141 M4OSA_DEBUG_IF1((M4OSA_NULL == pStreamContext), 142 M4ERR_PARAMETER, "M4DECODER_NULL_destroy: invalid context pointer"); 143 144 free(pStreamContext); 145 146 return M4NO_ERROR; 147 } 148 149 /** 150 ************************************************************************ 151 * @brief Get an option value from the decoder 152 * @note This function allows the caller to retrieve a property value: 153 * 154 * @param context: (IN) Context of the decoder 155 * @param optionId: (IN) Indicates the option to get 156 * @param pValue: (IN/OUT) Pointer to structure or value where 157 * option is stored 158 * 159 * @return M4NO_ERROR There is no error 160 * @return M4ERR_PARAMETER The context is invalid (in DEBUG only) 161 * @return M4ERR_BAD_OPTION_ID When the option ID is not a valid one 162 * @return M4ERR_STATE State automaton is not applied 163 * @return M4ERR_NOT_IMPLEMENTED Function not implemented 164 ************************************************************************ 165 */ 166 M4OSA_ERR M4DECODER_NULL_getOption(M4OSA_Context context, 167 M4OSA_OptionID optionId, 168 M4OSA_DataOption pValue) { 169 170 return M4ERR_NOT_IMPLEMENTED; 171 } 172 173 /** 174 ************************************************************************ 175 * @brief Set an option value of the decoder 176 * @note Allows the caller to set a property value: 177 * 178 * @param context: (IN) Context of the decoder 179 * @param optionId: (IN) Identifier indicating the option to set 180 * @param pValue: (IN) Pointer to structure or value 181 * where option is stored 182 * 183 * @return M4NO_ERROR There is no error 184 * @return M4ERR_BAD_OPTION_ID The option ID is not a valid one 185 * @return M4ERR_STATE State automaton is not applied 186 * @return M4ERR_PARAMETER The option parameter is invalid 187 ************************************************************************ 188 */ 189 M4OSA_ERR M4DECODER_NULL_setOption(M4OSA_Context context, 190 M4OSA_OptionID optionId, 191 M4OSA_DataOption pValue) { 192 193 M4DECODER_OutputFilter *pFilterOption; 194 195 M4_VideoHandler_Context *pStreamContext = 196 (M4_VideoHandler_Context*)context; 197 198 M4OSA_ERR err = M4NO_ERROR; 199 M4OSA_UInt32 height = 0; 200 M4OSA_UInt8 *p_src,*p_des; 201 M4VIFI_ImagePlane* pTempDecYuvData = M4OSA_NULL; 202 203 switch (optionId) { 204 case M4DECODER_kOptionID_DecYuvData: 205 pStreamContext->pDecYuvData = (M4VIFI_ImagePlane *)pValue; 206 break; 207 208 case M4DECODER_kOptionID_YuvWithEffectContiguous: 209 pStreamContext->pDecYuvWithEffect = (M4VIFI_ImagePlane *)pValue; 210 break; 211 212 case M4DECODER_kOptionID_EnableYuvWithEffect: 213 pStreamContext->bYuvWithEffectSet = (M4OSA_Bool)pValue; 214 break; 215 216 case M4DECODER_kOptionID_YuvWithEffectNonContiguous: 217 pTempDecYuvData = (M4VIFI_ImagePlane *)pValue; 218 219 p_des = pStreamContext->pDecYuvWithEffect[0].pac_data + 220 pStreamContext->pDecYuvWithEffect[0].u_topleft; 221 p_src = pTempDecYuvData[0].pac_data + 222 pTempDecYuvData[0].u_topleft; 223 224 for (height = 0; height<pStreamContext->pDecYuvWithEffect[0].u_height; 225 height++) { 226 memcpy((void *)p_des, (void *)p_src, 227 pStreamContext->pDecYuvWithEffect[0].u_width); 228 229 p_des += pStreamContext->pDecYuvWithEffect[0].u_stride; 230 p_src += pTempDecYuvData[0].u_stride; 231 } 232 233 p_des = pStreamContext->pDecYuvWithEffect[1].pac_data + 234 pStreamContext->pDecYuvWithEffect[1].u_topleft; 235 p_src = pTempDecYuvData[1].pac_data + 236 pTempDecYuvData[1].u_topleft; 237 238 for (height = 0; height<pStreamContext->pDecYuvWithEffect[1].u_height; 239 height++) { 240 memcpy((void *)p_des, (void *)p_src, 241 pStreamContext->pDecYuvWithEffect[1].u_width); 242 243 p_des += pStreamContext->pDecYuvWithEffect[1].u_stride; 244 p_src += pTempDecYuvData[1].u_stride; 245 } 246 247 p_des = pStreamContext->pDecYuvWithEffect[2].pac_data + 248 pStreamContext->pDecYuvWithEffect[2].u_topleft; 249 p_src = pTempDecYuvData[2].pac_data + 250 pTempDecYuvData[2].u_topleft; 251 252 for (height = 0; height<pStreamContext->pDecYuvWithEffect[2].u_height; 253 height++) { 254 memcpy((void *)p_des, (void *)p_src, 255 pStreamContext->pDecYuvWithEffect[2].u_width); 256 257 p_des += pStreamContext->pDecYuvWithEffect[2].u_stride; 258 p_src += pTempDecYuvData[2].u_stride; 259 } 260 break; 261 262 case M4DECODER_kOptionID_OutputFilter: 263 pFilterOption = (M4DECODER_OutputFilter*)pValue; 264 break; 265 266 case M4DECODER_kOptionID_DeblockingFilter: 267 err = M4ERR_BAD_OPTION_ID; 268 break; 269 270 default: 271 err = M4ERR_BAD_OPTION_ID; 272 break; 273 } 274 return err; 275 } 276 277 /** 278 ************************************************************************ 279 * @brief Decode video Access Units up to a target time 280 * @note Parse and decode the video until it can output a decoded image 281 * for which the composition time is equal or greater to the 282 * passed targeted time. 283 * The data are read from the reader data interface passed to 284 * M4DECODER_MPEG4_create. 285 * 286 * @param context: (IN) Context of the decoder 287 * @param pTime: (IN/OUT) IN: Time to decode up to (in msec) 288 * OUT:Time of the last decoded frame (in msec) 289 * @param bJump: (IN) 0 if no jump occured just before this call 290 * 1 if a a jump has just been made 291 * @return M4NO_ERROR there is no error 292 * @return M4ERR_PARAMETER at least one parameter is not properly set 293 * @return M4WAR_NO_MORE_AU there is no more access unit to decode (EOS) 294 ************************************************************************ 295 */ 296 M4OSA_ERR M4DECODER_NULL_decode(M4OSA_Context context, 297 M4_MediaTime* pTime, M4OSA_Bool bJump, 298 M4OSA_UInt32 tolerance) { 299 300 // Do nothing; input time stamp itself returned 301 return M4NO_ERROR; 302 } 303 304 /** 305 ************************************************************************ 306 * @brief Renders the video at the specified time. 307 * @note 308 * @param context: (IN) Context of the decoder 309 * @param pTime: (IN/OUT) IN: Time to render to (in msecs) 310 * OUT:Time of the rendered frame (in ms) 311 * @param pOutputPlane:(OUT) Output plane filled with decoded data 312 * @param bForceRender:(IN) 1 if the image must be rendered even it 313 * has been rendered already 314 * 0 if not 315 * 316 * @return M4NO_ERROR There is no error 317 * @return M4ERR_PARAMETER At least one parameter is not properly set 318 * @return M4ERR_STATE State automaton is not applied 319 * @return M4ERR_ALLOC There is no more available memory 320 * @return M4WAR_VIDEORENDERER_NO_NEW_FRAME If the frame has already been rendered 321 ************************************************************************ 322 */ 323 M4OSA_ERR M4DECODER_NULL_render(M4OSA_Context context, M4_MediaTime* pTime, 324 M4VIFI_ImagePlane* pOutputPlane, 325 M4OSA_Bool bForceRender) { 326 327 M4OSA_ERR err = M4NO_ERROR; 328 M4OSA_UInt32 height; 329 M4OSA_UInt8 *p_src,*p_des; 330 M4_VideoHandler_Context* pStreamContext = 331 (M4_VideoHandler_Context*)context; 332 333 if (pStreamContext->bYuvWithEffectSet == M4OSA_TRUE) { 334 335 p_des = pOutputPlane[0].pac_data + pOutputPlane[0].u_topleft; 336 p_src = pStreamContext->pDecYuvWithEffect[0].pac_data + 337 pStreamContext->pDecYuvWithEffect[0].u_topleft; 338 339 for (height = 0; height<pOutputPlane[0].u_height; height++) { 340 memcpy((void *)p_des, (void *)p_src, pOutputPlane[0].u_width); 341 p_des += pOutputPlane[0].u_stride; 342 p_src += pStreamContext->pDecYuvWithEffect[0].u_stride; 343 } 344 345 p_des = pOutputPlane[1].pac_data + pOutputPlane[1].u_topleft; 346 p_src = pStreamContext->pDecYuvWithEffect[1].pac_data + 347 pStreamContext->pDecYuvWithEffect[1].u_topleft; 348 349 for (height = 0; height<pOutputPlane[1].u_height; height++) { 350 memcpy((void *)p_des, (void *)p_src, pOutputPlane[1].u_width); 351 p_des += pOutputPlane[1].u_stride; 352 p_src += pStreamContext->pDecYuvWithEffect[1].u_stride; 353 } 354 355 p_des = pOutputPlane[2].pac_data + pOutputPlane[2].u_topleft; 356 p_src = pStreamContext->pDecYuvWithEffect[2].pac_data + 357 pStreamContext->pDecYuvWithEffect[2].u_topleft; 358 359 for (height = 0; height<pOutputPlane[2].u_height; height++) { 360 memcpy((void *)p_des, (void *)p_src, pOutputPlane[2].u_width); 361 p_des += pOutputPlane[2].u_stride; 362 p_src += pStreamContext->pDecYuvWithEffect[2].u_stride; 363 } 364 } else { 365 366 p_des = pOutputPlane[0].pac_data + pOutputPlane[0].u_topleft; 367 p_src = pStreamContext->pDecYuvData[0].pac_data + 368 pStreamContext->pDecYuvData[0].u_topleft; 369 370 for (height = 0; height<pOutputPlane[0].u_height; height++) { 371 memcpy((void *)p_des, (void *)p_src, pOutputPlane[0].u_width); 372 p_des += pOutputPlane[0].u_stride; 373 p_src += pStreamContext->pDecYuvData[0].u_stride; 374 } 375 376 p_des = pOutputPlane[1].pac_data + pOutputPlane[1].u_topleft; 377 p_src = pStreamContext->pDecYuvData[1].pac_data + 378 pStreamContext->pDecYuvData[1].u_topleft; 379 380 for (height = 0; height<pOutputPlane[1].u_height; height++) { 381 memcpy((void *)p_des, (void *)p_src, pOutputPlane[1].u_width); 382 p_des += pOutputPlane[1].u_stride; 383 p_src += pStreamContext->pDecYuvData[1].u_stride; 384 } 385 386 p_des = pOutputPlane[2].pac_data + pOutputPlane[2].u_topleft; 387 p_src = pStreamContext->pDecYuvData[2].pac_data + 388 pStreamContext->pDecYuvData[2].u_topleft; 389 390 for (height = 0; height<pOutputPlane[2].u_height; height++) { 391 memcpy((void *)p_des,(void *)p_src,pOutputPlane[2].u_width); 392 p_des += pOutputPlane[2].u_stride; 393 p_src += pStreamContext->pDecYuvData[2].u_stride; 394 } 395 } 396 return err; 397 } 398 399 /** 400 ************************************************************************ 401 * @brief Retrieves the interface implemented by the decoder 402 * @param pDecoderType : Pointer to a M4DECODER_VideoType 403 * (allocated by the caller) 404 * that will be filled with the decoder type 405 * @param pDecoderInterface : Address of a pointer that will be set to 406 * the interface implemented by this decoder. 407 * The interface is a structure allocated by 408 * this function and must be freed by the caller. 409 * 410 * @returns : M4NO_ERROR if OK 411 * M4ERR_ALLOC if allocation failed 412 ************************************************************************ 413 */ 414 M4OSA_ERR M4DECODER_NULL_getInterface (M4DECODER_VideoType *pDecoderType, 415 M4DECODER_VideoInterface **pDecoderInterface) { 416 417 *pDecoderInterface = 418 (M4DECODER_VideoInterface*)M4OSA_32bitAlignedMalloc( 419 sizeof(M4DECODER_VideoInterface), 420 M4DECODER_MPEG4, (M4OSA_Char *)"M4DECODER_VideoInterface"); 421 422 if (M4OSA_NULL == *pDecoderInterface) { 423 return M4ERR_ALLOC; 424 } 425 426 *pDecoderType = M4DECODER_kVideoTypeYUV420P; 427 428 (*pDecoderInterface)->m_pFctCreate = M4DECODER_NULL_create; 429 (*pDecoderInterface)->m_pFctDestroy = M4DECODER_NULL_destroy; 430 (*pDecoderInterface)->m_pFctGetOption = M4DECODER_NULL_getOption; 431 (*pDecoderInterface)->m_pFctSetOption = M4DECODER_NULL_setOption; 432 (*pDecoderInterface)->m_pFctDecode = M4DECODER_NULL_decode; 433 (*pDecoderInterface)->m_pFctRender = M4DECODER_NULL_render; 434 435 return M4NO_ERROR; 436 } 437