1 /* 2 * Copyright (c) 2009-2011 Intel Corporation. All rights reserved. 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 #include "VideoDecoderMPEG4.h" 18 #include "VideoDecoderTrace.h" 19 #include <string.h> 20 21 #define MAX_PICTURE_WIDTH_MPEG4 1920 22 #define MAX_PICTURE_HEIGHT_MPEG4 1088 23 24 VideoDecoderMPEG4::VideoDecoderMPEG4(const char *mimeType) 25 : VideoDecoderBase(mimeType, VBP_MPEG4), 26 mLastVOPTimeIncrement(0), 27 mExpectingNVOP(false), 28 mSendIQMatrixBuf(false), 29 mLastVOPCodingType(MP4_VOP_TYPE_I), 30 mIsShortHeader(false) { 31 } 32 33 VideoDecoderMPEG4::~VideoDecoderMPEG4() { 34 stop(); 35 } 36 37 Decode_Status VideoDecoderMPEG4::start(VideoConfigBuffer *buffer) { 38 Decode_Status status; 39 40 status = VideoDecoderBase::start(buffer); 41 CHECK_STATUS("VideoDecoderBase::start"); 42 43 if (buffer->data == NULL || buffer->size == 0) { 44 WTRACE("No config data to start VA."); 45 return DECODE_SUCCESS; 46 } 47 48 vbp_data_mp42 *data = NULL; 49 status = VideoDecoderBase::parseBuffer(buffer->data, buffer->size, true, (void**)&data); 50 CHECK_STATUS("VideoDecoderBase::parseBuffer"); 51 52 if (data->codec_data.video_object_layer_width > MAX_PICTURE_WIDTH_MPEG4 || 53 data->codec_data.video_object_layer_height > MAX_PICTURE_HEIGHT_MPEG4) { 54 return DECODE_INVALID_DATA; 55 } 56 57 status = startVA(data); 58 return status; 59 } 60 61 void VideoDecoderMPEG4::stop(void) { 62 // drop the last frame and ignore return value 63 endDecodingFrame(true); 64 VideoDecoderBase::stop(); 65 66 mLastVOPTimeIncrement = 0; 67 mExpectingNVOP = false; 68 mLastVOPCodingType = MP4_VOP_TYPE_I; 69 } 70 71 Decode_Status VideoDecoderMPEG4::decode(VideoDecodeBuffer *buffer) { 72 Decode_Status status; 73 vbp_data_mp42 *data = NULL; 74 bool useGraphicbuffer = mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER; 75 if (buffer == NULL) { 76 return DECODE_INVALID_DATA; 77 } 78 if (buffer->flag & IS_SYNC_FRAME) { 79 mIsSyncFrame = true; 80 } else { 81 mIsSyncFrame = false; 82 } 83 buffer->ext = NULL; 84 status = VideoDecoderBase::parseBuffer( 85 buffer->data, 86 buffer->size, 87 false, 88 (void**)&data); 89 CHECK_STATUS("VideoDecoderBase::parseBuffer"); 90 91 if (data->codec_data.video_object_layer_width > MAX_PICTURE_WIDTH_MPEG4 || 92 data->codec_data.video_object_layer_height > MAX_PICTURE_HEIGHT_MPEG4) { 93 return DECODE_INVALID_DATA; 94 } 95 96 if (!mVAStarted) { 97 status = startVA(data); 98 CHECK_STATUS("startVA"); 99 } 100 101 if (mSizeChanged && !useGraphicbuffer) { 102 // some container has the incorrect width/height. 103 // send the format change to OMX to update the crop info. 104 mSizeChanged = false; 105 ITRACE("Video size is changed during startVA"); 106 return DECODE_FORMAT_CHANGE; 107 } 108 109 if ((mVideoFormatInfo.width != (uint32_t)data->codec_data.video_object_layer_width || 110 mVideoFormatInfo.height != (uint32_t)data->codec_data.video_object_layer_height) && 111 data->codec_data.video_object_layer_width && 112 data->codec_data.video_object_layer_height) { 113 // update encoded image size 114 ITRACE("Video size is changed. from %dx%d to %dx%d\n", mVideoFormatInfo.width, mVideoFormatInfo.height, 115 data->codec_data.video_object_layer_width,data->codec_data.video_object_layer_height); 116 117 if (useGraphicbuffer && mStoreMetaData) { 118 pthread_mutex_lock(&mFormatLock); 119 } 120 mVideoFormatInfo.width = data->codec_data.video_object_layer_width; 121 mVideoFormatInfo.height = data->codec_data.video_object_layer_height; 122 bool needFlush = false; 123 if (useGraphicbuffer) { 124 if (mStoreMetaData) { 125 needFlush = true; 126 127 mVideoFormatInfo.valid = false; 128 pthread_mutex_unlock(&mFormatLock); 129 } else { 130 needFlush = (mVideoFormatInfo.width > mVideoFormatInfo.surfaceWidth) 131 || (mVideoFormatInfo.height > mVideoFormatInfo.surfaceHeight); 132 } 133 } 134 if (needFlush) { 135 if (mStoreMetaData) { 136 status = endDecodingFrame(false); 137 CHECK_STATUS("endDecodingFrame"); 138 } else { 139 flushSurfaceBuffers(); 140 } 141 mSizeChanged = false; 142 return DECODE_FORMAT_CHANGE; 143 } else { 144 mSizeChanged = true; 145 } 146 147 setRenderRect(); 148 } else { 149 if (useGraphicbuffer && mStoreMetaData) { 150 mVideoFormatInfo.valid = true; 151 } 152 } 153 154 status = decodeFrame(buffer, data); 155 CHECK_STATUS("decodeFrame"); 156 157 return status; 158 } 159 160 void VideoDecoderMPEG4::flush(void) { 161 VideoDecoderBase::flush(); 162 163 mExpectingNVOP = false; 164 mLastVOPTimeIncrement = 0; 165 mLastVOPCodingType = MP4_VOP_TYPE_I; 166 } 167 168 Decode_Status VideoDecoderMPEG4::decodeFrame(VideoDecodeBuffer *buffer, vbp_data_mp42 *data) { 169 Decode_Status status; 170 // check if any slice is parsed, we may just receive configuration data 171 if (data->number_picture_data == 0) { 172 WTRACE("number_picture_data == 0"); 173 return DECODE_SUCCESS; 174 } 175 if (data->picture_data && (data->picture_data->picture_param.vop_width == 0 || data->picture_data->picture_param.vop_height == 0)) { 176 if (!data->codec_data.got_vol && data->codec_data.got_vop) { 177 // error enhancement if vol is missing 178 data->picture_data->picture_param.vop_width = mVideoFormatInfo.width; 179 data->picture_data->picture_param.vop_height = mVideoFormatInfo.height; 180 } else { 181 return DECODE_PARSER_FAIL; 182 } 183 } 184 185 uint64_t lastPTS = mCurrentPTS; 186 mCurrentPTS = buffer->timeStamp; 187 188 if (lastPTS != mCurrentPTS) { 189 // finish decoding the last frame 190 status = endDecodingFrame(false); 191 CHECK_STATUS("endDecodingFrame"); 192 193 // start decoding a new frame 194 status = beginDecodingFrame(data); 195 if (status == DECODE_MULTIPLE_FRAME) { 196 buffer->ext = &mExtensionBuffer; 197 mExtensionBuffer.extType = PACKED_FRAME_TYPE; 198 mExtensionBuffer.extSize = sizeof(mPackedFrame); 199 mExtensionBuffer.extData = (uint8_t*)&mPackedFrame; 200 } else if (status != DECODE_SUCCESS) { 201 endDecodingFrame(true); 202 } 203 CHECK_STATUS("beginDecodingFrame"); 204 } else { 205 status = continueDecodingFrame(data); 206 if (status == DECODE_MULTIPLE_FRAME) { 207 buffer->ext = &mExtensionBuffer; 208 mExtensionBuffer.extType = PACKED_FRAME_TYPE; 209 mExtensionBuffer.extSize = sizeof(mPackedFrame); 210 mExtensionBuffer.extData = (uint8_t*)&mPackedFrame; 211 } else if (status != DECODE_SUCCESS) { 212 endDecodingFrame(true); 213 } 214 CHECK_STATUS("continueDecodingFrame"); 215 } 216 217 if (buffer->flag & HAS_COMPLETE_FRAME) { 218 // finish decoding current frame 219 status = endDecodingFrame(false); 220 CHECK_STATUS("endDecodingFrame"); 221 } 222 223 return DECODE_SUCCESS; 224 } 225 226 Decode_Status VideoDecoderMPEG4::beginDecodingFrame(vbp_data_mp42 *data) { 227 228 Decode_Status status = DECODE_SUCCESS; 229 vbp_picture_data_mp42 *picData = data->picture_data; 230 VAPictureParameterBufferMPEG4 *picParam = &(picData->picture_param); 231 int codingType = picParam->vop_fields.bits.vop_coding_type; 232 233 // start sanity checking 234 if (mExpectingNVOP) { 235 // if we are waiting for n-vop for packed frame, and the new frame is coded, the coding type 236 // of this frame must be B 237 // for example: {PB} B N P B B P... 238 if (picData->vop_coded == 1 && codingType != MP4_VOP_TYPE_B) { 239 WTRACE("Invalid coding type while waiting for n-vop for packed frame."); 240 mExpectingNVOP = false; 241 } 242 } 243 244 // handle N-VOP picuture, it could be a skipped frame or a simple placeholder of packed frame 245 if (picData->vop_coded == 0) { 246 if (mLastReference == NULL) { 247 WTRACE("The last reference is unavailable to construct skipped frame."); 248 flush(); 249 mExpectingNVOP = false; 250 // TODO: handle this case 251 return DECODE_SUCCESS; 252 } 253 254 if (mExpectingNVOP) { 255 // P frame is already in queue, just need to update time stamp. 256 mLastReference->renderBuffer.timeStamp = mCurrentPTS; 257 mExpectingNVOP = false; 258 } 259 else { 260 // Do nothing for skip frame as the last frame will be rendered agian by natively 261 // No needs to handle reference frame neither 262 #if 0 263 // this is skipped frame, use the last reference frame as output 264 status = acquireSurfaceBuffer(); 265 CHECK_STATUS("acquireSurfaceBuffer"); 266 mAcquiredBuffer->renderBuffer.timeStamp = mCurrentPTS; 267 mAcquiredBuffer->renderBuffer.flag = 0; 268 mAcquiredBuffer->renderBuffer.scanFormat = mLastReference->renderBuffer.scanFormat; 269 mAcquiredBuffer->renderBuffer.surface = mLastReference->renderBuffer.surface; 270 // No need to update mappedData for HW decoding 271 //mAcquiredBuffer->mappedData.data = mLastReference->mappedData.data; 272 mAcquiredBuffer->referenceFrame = true; 273 status = outputSurfaceBuffer(); 274 CHECK_STATUS("outputSurfaceBuffer"); 275 #endif 276 } 277 278 if (data->number_picture_data > 1) { 279 WTRACE("Unexpected to have more picture data following a non-coded VOP."); 280 //picture data is thrown away. No issue if picture data is for N-VOP. if picture data is for 281 // coded picture, a frame is lost. 282 // TODO: handle this case 283 // return DECODE_FAIL; 284 } 285 return DECODE_SUCCESS; 286 } 287 else { 288 // Check if we have reference frame(s) for decoding 289 if (codingType == MP4_VOP_TYPE_B) { 290 if (mForwardReference == NULL || 291 mLastReference == NULL) { 292 if (mIsShortHeader) { 293 status = DECODE_SUCCESS; 294 VTRACE("%s: No reference frame but keep decoding", __FUNCTION__); 295 } else 296 return DECODE_NO_REFERENCE; 297 } 298 } else if (codingType == MP4_VOP_TYPE_P || codingType == MP4_VOP_TYPE_S) { 299 if (mLastReference == NULL && mIsSyncFrame == false) { 300 if (mIsShortHeader) { 301 status = DECODE_SUCCESS; 302 VTRACE("%s: No reference frame but keep decoding", __FUNCTION__); 303 } else 304 return DECODE_NO_REFERENCE; 305 } 306 } 307 // all sanity checks pass, continue decoding through continueDecodingFrame 308 status = continueDecodingFrame(data); 309 } 310 return status; 311 } 312 313 Decode_Status VideoDecoderMPEG4::continueDecodingFrame(vbp_data_mp42 *data) { 314 Decode_Status status = DECODE_SUCCESS; 315 VAStatus vaStatus = VA_STATUS_SUCCESS; 316 bool useGraphicBuffer = mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER; 317 318 /* 319 Packed Frame Assumption: 320 321 1. In one packed frame, there's only one P or I frame and only one B frame. 322 2. In packed frame, there's no skipped frame (vop_coded = 0) 323 3. For one packed frame, there will be one N-VOP frame to follow the packed frame (may not immediately). 324 4. N-VOP frame is the frame with vop_coded = 0. 325 5. The timestamp of N-VOP frame will be used for P or I frame in the packed frame 326 327 328 I, P, {P, B}, B, N, P, N, I, ... 329 I, P, {P, B}, N, P, N, I, ... 330 331 The first N is placeholder for P frame in the packed frame 332 The second N is a skipped frame 333 */ 334 335 vbp_picture_data_mp42 *picData = data->picture_data; 336 for (uint32_t i = 0; i < data->number_picture_data; i++, picData = picData->next_picture_data) { 337 // each slice has its own picture data, video_packet_header following resync_marker may reset picture header, see MP4 spec 338 VAPictureParameterBufferMPEG4 *picParam = &(picData->picture_param); 339 int codingType = picParam->vop_fields.bits.vop_coding_type; 340 if (codingType == MP4_VOP_TYPE_S && picParam->no_of_sprite_warping_points > 1) { 341 WTRACE("Hardware only supports up to one warping point (stationary or translation)"); 342 } 343 344 if (picData->vop_coded == 0) { 345 ETRACE("Unexpected to have non-coded VOP."); 346 return DECODE_FAIL; 347 } 348 if (picData->new_picture_flag == 1 || mDecodingFrame == false) { 349 // either condition indicates start of a new frame 350 if (picData->new_picture_flag == 0) { 351 WTRACE("First slice of picture is lost!"); 352 // TODO: handle this case 353 } 354 if (mDecodingFrame) { 355 if (codingType == MP4_VOP_TYPE_B){ 356 // this indicates the start of a new frame in the packed frame 357 // Update timestamp for P frame in the packed frame as timestamp here is for the B frame! 358 if (picParam->vop_time_increment_resolution){ 359 uint64_t increment = mLastVOPTimeIncrement - picData->vop_time_increment + 360 picParam->vop_time_increment_resolution; 361 increment = increment % picParam->vop_time_increment_resolution; 362 // convert to micro-second 363 // TODO: unit of time stamp varies on different frame work 364 increment = increment * 1e6 / picParam->vop_time_increment_resolution; 365 mAcquiredBuffer->renderBuffer.timeStamp += increment; 366 if (useGraphicBuffer){ 367 mPackedFrame.timestamp = mCurrentPTS; 368 mCurrentPTS = mAcquiredBuffer->renderBuffer.timeStamp; 369 } 370 } 371 } else { 372 // this indicates the start of a new frame in the packed frame. no B frame int the packet 373 // Update the timestamp according the increment 374 if (picParam->vop_time_increment_resolution){ 375 int64_t increment = picData->vop_time_increment - mLastVOPTimeIncrement + picParam->vop_time_increment_resolution; 376 increment = increment % picParam->vop_time_increment_resolution; 377 //convert to micro-second 378 increment = increment * 1e6 / picParam->vop_time_increment_resolution; 379 if (useGraphicBuffer) { 380 mPackedFrame.timestamp = mCurrentPTS + increment; 381 } 382 else { 383 mCurrentPTS += increment; 384 } 385 386 } else { 387 if (useGraphicBuffer) { 388 mPackedFrame.timestamp = mCurrentPTS + 30000; 389 } 390 else { 391 mCurrentPTS += 30000; 392 } 393 } 394 } 395 endDecodingFrame(false); 396 mExpectingNVOP = true; 397 if (codingType != MP4_VOP_TYPE_B) { 398 mExpectingNVOP = false; 399 } 400 if (useGraphicBuffer) { 401 int32_t count = i - 1; 402 if (count < 0) { 403 WTRACE("Shuld not be here!"); 404 return DECODE_SUCCESS; 405 } 406 vbp_picture_data_mp42 *lastpic = data->picture_data; 407 for(int k = 0; k < count; k++ ) { 408 lastpic = lastpic->next_picture_data; 409 } 410 mPackedFrame.offSet = lastpic->slice_data.slice_offset + lastpic->slice_data.slice_size; 411 VTRACE("Report OMX to handle for Multiple frame offset=%d time=%lld",mPackedFrame.offSet,mPackedFrame.timestamp); 412 return DECODE_MULTIPLE_FRAME; 413 } 414 } 415 416 // acquire a new surface buffer 417 status = acquireSurfaceBuffer(); 418 CHECK_STATUS("acquireSurfaceBuffer"); 419 420 // sprite is treated as P frame in the display order, so only B frame frame is not used as "reference" 421 mAcquiredBuffer->referenceFrame = (codingType != MP4_VOP_TYPE_B); 422 if (picData->picture_param.vol_fields.bits.interlaced) { 423 // only MPEG-4 studio profile can have field coding. All other profiles 424 // use frame coding only, i.e, there is no field VOP. (see vop_structure in MP4 spec) 425 mAcquiredBuffer->renderBuffer.scanFormat = VA_BOTTOM_FIELD | VA_TOP_FIELD; 426 } else { 427 mAcquiredBuffer->renderBuffer.scanFormat = VA_FRAME_PICTURE; 428 } 429 // TODO: set discontinuity flag 430 mAcquiredBuffer->renderBuffer.flag = 0; 431 mAcquiredBuffer->renderBuffer.timeStamp = mCurrentPTS; 432 if (mSizeChanged) { 433 mAcquiredBuffer->renderBuffer.flag |= IS_RESOLUTION_CHANGE; 434 mSizeChanged = false; 435 } 436 if (codingType != MP4_VOP_TYPE_B) { 437 mLastVOPCodingType = codingType; 438 mLastVOPTimeIncrement = picData->vop_time_increment; 439 } 440 441 // start decoding a frame 442 vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface); 443 CHECK_VA_STATUS("vaBeginPicture"); 444 445 mDecodingFrame = true; 446 mSendIQMatrixBuf = true; 447 } 448 449 status = decodeSlice(data, picData); 450 CHECK_STATUS("decodeSlice"); 451 } 452 453 return DECODE_SUCCESS; 454 } 455 456 457 Decode_Status VideoDecoderMPEG4::decodeSlice(vbp_data_mp42 *data, vbp_picture_data_mp42 *picData) { 458 Decode_Status status; 459 VAStatus vaStatus; 460 uint32_t bufferIDCount = 0; 461 // maximum 4 buffers to render a slice: picture parameter, IQMatrix, slice parameter, slice data 462 VABufferID bufferIDs[4]; 463 464 VAPictureParameterBufferMPEG4 *picParam = &(picData->picture_param); 465 vbp_slice_data_mp42 *sliceData = &(picData->slice_data); 466 VASliceParameterBufferMPEG4 *sliceParam = &(sliceData->slice_param); 467 468 // send picture parametre for each slice 469 status = setReference(picParam); 470 CHECK_STATUS("setReference"); 471 472 vaStatus = vaCreateBuffer( 473 mVADisplay, 474 mVAContext, 475 VAPictureParameterBufferType, 476 sizeof(VAPictureParameterBufferMPEG4), 477 1, 478 picParam, 479 &bufferIDs[bufferIDCount]); 480 CHECK_VA_STATUS("vaCreatePictureParameterBuffer"); 481 482 bufferIDCount++; 483 if (picParam->vol_fields.bits.quant_type && mSendIQMatrixBuf) 484 { 485 // only send IQ matrix for the first slice in the picture 486 vaStatus = vaCreateBuffer( 487 mVADisplay, 488 mVAContext, 489 VAIQMatrixBufferType, 490 sizeof(VAIQMatrixBufferMPEG4), 491 1, 492 &(data->iq_matrix_buffer), 493 &bufferIDs[bufferIDCount]); 494 CHECK_VA_STATUS("vaCreateIQMatrixBuffer"); 495 496 mSendIQMatrixBuf = false; 497 bufferIDCount++; 498 } 499 500 vaStatus = vaCreateBuffer( 501 mVADisplay, 502 mVAContext, 503 VASliceParameterBufferType, 504 sizeof(VASliceParameterBufferMPEG4), 505 1, 506 sliceParam, 507 &bufferIDs[bufferIDCount]); 508 CHECK_VA_STATUS("vaCreateSliceParameterBuffer"); 509 510 bufferIDCount++; 511 512 //slice data buffer pointer 513 //Note that this is the original data buffer ptr; 514 // offset to the actual slice data is provided in 515 // slice_data_offset in VASliceParameterBufferMP42 516 517 vaStatus = vaCreateBuffer( 518 mVADisplay, 519 mVAContext, 520 VASliceDataBufferType, 521 sliceData->slice_size, //size 522 1, //num_elements 523 sliceData->buffer_addr + sliceData->slice_offset, 524 &bufferIDs[bufferIDCount]); 525 CHECK_VA_STATUS("vaCreateSliceDataBuffer"); 526 527 bufferIDCount++; 528 529 vaStatus = vaRenderPicture( 530 mVADisplay, 531 mVAContext, 532 bufferIDs, 533 bufferIDCount); 534 CHECK_VA_STATUS("vaRenderPicture"); 535 536 537 return DECODE_SUCCESS; 538 } 539 540 Decode_Status VideoDecoderMPEG4::setReference(VAPictureParameterBufferMPEG4 *picParam) { 541 switch (picParam->vop_fields.bits.vop_coding_type) { 542 case MP4_VOP_TYPE_I: 543 picParam->forward_reference_picture = VA_INVALID_SURFACE; 544 picParam->backward_reference_picture = VA_INVALID_SURFACE; 545 break; 546 case MP4_VOP_TYPE_P: 547 if (mLastReference == NULL && mIsSyncFrame == false && !mIsShortHeader) { 548 return DECODE_NO_REFERENCE; 549 } 550 if (mLastReference != NULL) { 551 picParam->forward_reference_picture = mLastReference->renderBuffer.surface; 552 } else { 553 VTRACE("%s: no reference frame, but keep decoding", __FUNCTION__); 554 picParam->forward_reference_picture = VA_INVALID_SURFACE; 555 } 556 picParam->backward_reference_picture = VA_INVALID_SURFACE; 557 break; 558 case MP4_VOP_TYPE_B: 559 picParam->vop_fields.bits.backward_reference_vop_coding_type = mLastVOPCodingType; 560 // WEIRD, CHECK AGAIN !!!!!!! 561 if (mIsShortHeader) { 562 if (mLastReference != NULL) { 563 picParam->forward_reference_picture = mLastReference->renderBuffer.surface; 564 } else { 565 VTRACE("%s: no forward reference frame, but keep decoding", __FUNCTION__); 566 picParam->forward_reference_picture = VA_INVALID_SURFACE; 567 } 568 if (mForwardReference != NULL) { 569 picParam->backward_reference_picture = mForwardReference->renderBuffer.surface; 570 } else { 571 VTRACE("%s: no backward reference frame, but keep decoding", __FUNCTION__); 572 picParam->backward_reference_picture = VA_INVALID_SURFACE; 573 } 574 } else if (mLastReference == NULL || mForwardReference == NULL) { 575 return DECODE_NO_REFERENCE; 576 } else { 577 picParam->forward_reference_picture = mLastReference->renderBuffer.surface; 578 picParam->backward_reference_picture = mForwardReference->renderBuffer.surface; 579 } 580 break; 581 case MP4_VOP_TYPE_S: 582 // WEIRD, CHECK AGAIN!!!! WAS using mForwardReference 583 if (mLastReference == NULL) { 584 return DECODE_NO_REFERENCE; 585 } 586 picParam->forward_reference_picture = mLastReference->renderBuffer.surface; 587 picParam->backward_reference_picture = VA_INVALID_SURFACE; 588 break; 589 590 default: 591 // Will never reach here; 592 return DECODE_PARSER_FAIL; 593 } 594 return DECODE_SUCCESS; 595 } 596 597 Decode_Status VideoDecoderMPEG4::startVA(vbp_data_mp42 *data) { 598 updateFormatInfo(data); 599 600 VAProfile vaProfile; 601 602 if ((data->codec_data.profile_and_level_indication & 0xF8) == 0xF0) { 603 vaProfile = VAProfileMPEG4AdvancedSimple; 604 } else { 605 vaProfile = VAProfileMPEG4Simple; 606 } 607 608 mIsShortHeader = data->codec_data.short_video_header; 609 610 return VideoDecoderBase::setupVA(MP4_SURFACE_NUMBER, vaProfile); 611 } 612 613 void VideoDecoderMPEG4::updateFormatInfo(vbp_data_mp42 *data) { 614 ITRACE("updateFormatInfo: current size: %d x %d, new size: %d x %d", 615 mVideoFormatInfo.width, mVideoFormatInfo.height, 616 data->codec_data.video_object_layer_width, 617 data->codec_data.video_object_layer_height); 618 // error enhancement if vol is missing 619 if (!data->codec_data.got_vol && data->codec_data.got_vop) { 620 data->codec_data.video_object_layer_width = mVideoFormatInfo.width; 621 data->codec_data.video_object_layer_height = mVideoFormatInfo.height; 622 } 623 624 mVideoFormatInfo.cropBottom = data->codec_data.video_object_layer_height > mVideoFormatInfo.height ? 625 data->codec_data.video_object_layer_height - mVideoFormatInfo.height : 0; 626 mVideoFormatInfo.cropRight = data->codec_data.video_object_layer_width > mVideoFormatInfo.width ? 627 data->codec_data.video_object_layer_width - mVideoFormatInfo.width : 0; 628 629 if ((mVideoFormatInfo.width != (uint32_t)data->codec_data.video_object_layer_width || 630 mVideoFormatInfo.height != (uint32_t)data->codec_data.video_object_layer_height) && 631 data->codec_data.video_object_layer_width && 632 data->codec_data.video_object_layer_height) { 633 // update encoded image size 634 mVideoFormatInfo.width = data->codec_data.video_object_layer_width; 635 mVideoFormatInfo.height = data->codec_data.video_object_layer_height; 636 mSizeChanged = true; 637 ITRACE("Video size is changed."); 638 } 639 640 // video_range has default value of 0. Y ranges from 16 to 235. 641 mVideoFormatInfo.videoRange = data->codec_data.video_range; 642 643 switch (data->codec_data.matrix_coefficients) { 644 case 1: 645 mVideoFormatInfo.colorMatrix = VA_SRC_BT709; 646 break; 647 648 // ITU-R Recommendation BT.470-6 System B, G (MP4), same as 649 // SMPTE 170M/BT601 650 case 5: 651 case 6: 652 mVideoFormatInfo.colorMatrix = VA_SRC_BT601; 653 break; 654 655 default: 656 // unknown color matrix, set to 0 so color space flag will not be set. 657 mVideoFormatInfo.colorMatrix = 0; 658 break; 659 } 660 661 mVideoFormatInfo.aspectX = data->codec_data.par_width; 662 mVideoFormatInfo.aspectY = data->codec_data.par_height; 663 //mVideoFormatInfo.bitrate = data->codec_data.bit_rate; 664 mVideoFormatInfo.valid = true; 665 666 setRenderRect(); 667 setColorSpaceInfo(mVideoFormatInfo.colorMatrix, mVideoFormatInfo.videoRange); 668 } 669 670 Decode_Status VideoDecoderMPEG4::checkHardwareCapability() { 671 VAStatus vaStatus; 672 VAConfigAttrib cfgAttribs[2]; 673 cfgAttribs[0].type = VAConfigAttribMaxPictureWidth; 674 cfgAttribs[1].type = VAConfigAttribMaxPictureHeight; 675 vaStatus = vaGetConfigAttributes(mVADisplay, 676 mIsShortHeader ? VAProfileH263Baseline : VAProfileMPEG4AdvancedSimple, 677 VAEntrypointVLD, cfgAttribs, 2); 678 CHECK_VA_STATUS("vaGetConfigAttributes"); 679 if (cfgAttribs[0].value * cfgAttribs[1].value < (uint32_t)mVideoFormatInfo.width * (uint32_t)mVideoFormatInfo.height) { 680 ETRACE("hardware supports resolution %d * %d smaller than the clip resolution %d * %d", 681 cfgAttribs[0].value, cfgAttribs[1].value, mVideoFormatInfo.width, mVideoFormatInfo.height); 682 return DECODE_DRIVER_FAIL; 683 } 684 685 return DECODE_SUCCESS; 686 } 687