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 "VideoDecoderWMV.h" 18#include "VideoDecoderTrace.h" 19#include <string.h> 20 21#define MAX_PICTURE_WIDTH_VC1 1920 22#define MAX_PICTURE_HEIGHT_VC1 1088 23 24VideoDecoderWMV::VideoDecoderWMV(const char *mimeType) 25 : VideoDecoderBase(mimeType, VBP_VC1), 26 mBufferIDs(NULL), 27 mNumBufferIDs(0), 28 mConfigDataParsed(false), 29 mRangeMapped(false), 30 mDeblockedCurrPicIndex(0), 31 mDeblockedLastPicIndex(1), 32 mDeblockedForwardPicIndex(2) { 33} 34 35 36VideoDecoderWMV::~VideoDecoderWMV() { 37 stop(); 38} 39 40Decode_Status VideoDecoderWMV::start(VideoConfigBuffer *buffer) { 41 Decode_Status status; 42 43 status = VideoDecoderBase::start(buffer); 44 CHECK_STATUS("VideoDecoderBase::start"); 45 46 if (buffer->data == NULL || buffer->size == 0) { 47 WTRACE("No config data to start VA."); 48 return DECODE_SUCCESS; 49 } 50 51 vbp_data_vc1 *data = NULL; 52 status = parseBuffer(buffer->data, buffer->size, &data); 53 CHECK_STATUS("parseBuffer"); 54 55 if (data->se_data->CODED_WIDTH > MAX_PICTURE_WIDTH_VC1 || 56 data->se_data->CODED_HEIGHT > MAX_PICTURE_HEIGHT_VC1) { 57 return DECODE_INVALID_DATA; 58 } 59 60 status = startVA(data); 61 return status; 62} 63 64void VideoDecoderWMV::stop(void) { 65 if (mBufferIDs) { 66 delete [] mBufferIDs; 67 mBufferIDs = NULL; 68 } 69 mNumBufferIDs = 0; 70 mConfigDataParsed = false; 71 mRangeMapped = false; 72 73 mDeblockedCurrPicIndex = 0; 74 mDeblockedLastPicIndex = 1; 75 mDeblockedForwardPicIndex = 2; 76 77 VideoDecoderBase::stop(); 78} 79 80void VideoDecoderWMV::flush(void) { 81 VideoDecoderBase::flush(); 82 83 mRangeMapped = false; 84 mDeblockedCurrPicIndex = 0; 85 mDeblockedLastPicIndex = 1; 86 mDeblockedForwardPicIndex = 2; 87} 88 89Decode_Status VideoDecoderWMV::decode(VideoDecodeBuffer *buffer) { 90 Decode_Status status; 91 vbp_data_vc1 *data = NULL; 92 bool useGraphicbuffer = mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER; 93 if (buffer == NULL) { 94 return DECODE_INVALID_DATA; 95 } 96 97 status = parseBuffer(buffer->data, buffer->size, &data); 98 CHECK_STATUS("parseBuffer"); 99 100 if (data->se_data->CODED_WIDTH > MAX_PICTURE_WIDTH_VC1 || 101 data->se_data->CODED_HEIGHT > MAX_PICTURE_HEIGHT_VC1) { 102 return DECODE_INVALID_DATA; 103 } 104 105 if (!mVAStarted) { 106 status = startVA(data); 107 CHECK_STATUS("startVA"); 108 } 109 110 if (mSizeChanged && !useGraphicbuffer) { 111 mSizeChanged = false; 112 return DECODE_FORMAT_CHANGE; 113 } 114 115 if ((mVideoFormatInfo.width != data->se_data->CODED_WIDTH || 116 mVideoFormatInfo.height != data->se_data->CODED_HEIGHT) && 117 data->se_data->CODED_WIDTH && 118 data->se_data->CODED_HEIGHT) { 119 ITRACE("video size is changed from %dx%d to %dx%d", mVideoFormatInfo.width, mVideoFormatInfo.height, 120 data->se_data->CODED_WIDTH, data->se_data->CODED_HEIGHT); 121 if (useGraphicbuffer && mStoreMetaData) { 122 pthread_mutex_lock(&mFormatLock); 123 } 124 mVideoFormatInfo.width = data->se_data->CODED_WIDTH; 125 mVideoFormatInfo.height = data->se_data->CODED_HEIGHT; 126 bool needFlush = false; 127 if (useGraphicbuffer) { 128 if (mStoreMetaData) { 129 needFlush = true; 130 131 mVideoFormatInfo.valid = false; 132 pthread_mutex_unlock(&mFormatLock); 133 } else { 134 needFlush = (mVideoFormatInfo.width > mVideoFormatInfo.surfaceWidth) 135 || (mVideoFormatInfo.height > mVideoFormatInfo.surfaceHeight); 136 } 137 } 138 139 setRenderRect(); 140 141 if (needFlush) { 142 if (mStoreMetaData) { 143 status = endDecodingFrame(false); 144 CHECK_STATUS("endDecodingFrame"); 145 } else { 146 flushSurfaceBuffers(); 147 } 148 mSizeChanged = false; 149 return DECODE_FORMAT_CHANGE; 150 } else { 151 mSizeChanged = true; 152 } 153 } else { 154 if (useGraphicbuffer && mStoreMetaData) { 155 mVideoFormatInfo.valid = true; 156 } 157 } 158 159 status = decodeFrame(buffer, data); 160 CHECK_STATUS("decodeFrame"); 161 return status; 162} 163 164Decode_Status VideoDecoderWMV::decodeFrame(VideoDecodeBuffer* buffer, vbp_data_vc1 *data) { 165 Decode_Status status; 166 mCurrentPTS = buffer->timeStamp; 167 if (0 == data->num_pictures || NULL == data->pic_data) { 168 WTRACE("Number of pictures is 0, buffer contains configuration data only?"); 169 return DECODE_SUCCESS; 170 } 171 172 if (data->pic_data[0].picture_is_skipped == VC1_PTYPE_SKIPPED) { 173 174 // Do nothing for skip frame as the last frame will be rendered agian by natively 175 // No needs to handle reference frame neither 176 return DECODE_SUCCESS; 177#if 0 178 //use the last P or I frame surface for skipped frame and treat it as P frame 179 if (mLastReference == NULL) { 180 // TODO: handle this case 181 WTRACE("The last reference is unavailable to construct skipped frame."); 182 return DECODE_SUCCESS; 183 } 184 185 status = acquireSurfaceBuffer(); 186 CHECK_STATUS("acquireSurfaceBuffer"); 187 mAcquiredBuffer->renderBuffer.timeStamp = mCurrentPTS; 188 mAcquiredBuffer->renderBuffer.flag = 0; 189 mAcquiredBuffer->renderBuffer.scanFormat = mLastReference->renderBuffer.scanFormat; 190 mAcquiredBuffer->renderBuffer.surface = mLastReference->renderBuffer.surface; 191 // No need to update mappedData for HW decoding 192 //mAcquiredBuffer->mappedData.data = mLastReference->mappedData.data; 193 mAcquiredBuffer->referenceFrame = true; 194 // let outputSurfaceBuffer handle "asReference" for VC1 195 status = outputSurfaceBuffer(); 196 return status; 197#endif 198 } 199 200 status = acquireSurfaceBuffer(); 201 CHECK_STATUS("acquireSurfaceBuffer"); 202 203 mAcquiredBuffer->renderBuffer.timeStamp = buffer->timeStamp; 204 if (buffer->flag & HAS_DISCONTINUITY) { 205 mAcquiredBuffer->renderBuffer.flag |= HAS_DISCONTINUITY; 206 } 207 if (buffer->flag & WANT_DECODE_ONLY) { 208 mAcquiredBuffer->renderBuffer.flag |= WANT_DECODE_ONLY; 209 } 210 if (mSizeChanged) { 211 mSizeChanged = false; 212 mAcquiredBuffer->renderBuffer.flag |= IS_RESOLUTION_CHANGE; 213 } 214 215 if (data->num_pictures > 1) { 216 if (data->pic_data[0].pic_parms->picture_fields.bits.is_first_field) { 217 mAcquiredBuffer->renderBuffer.scanFormat = VA_TOP_FIELD; 218 } else { 219 mAcquiredBuffer->renderBuffer.scanFormat = VA_BOTTOM_FIELD; 220 } 221 } else { 222 mAcquiredBuffer->renderBuffer.scanFormat = VA_FRAME_PICTURE; 223 } 224 225 mRangeMapped = (data->se_data->RANGE_MAPY_FLAG || data->se_data->RANGE_MAPUV_FLAG || data->se_data->RANGERED); 226 227 int frameType = data->pic_data[0].pic_parms->picture_fields.bits.picture_type; 228 mAcquiredBuffer->referenceFrame = (frameType == VC1_PTYPE_I || frameType == VC1_PTYPE_P); 229 230 // TODO: handle multiple frames parsed from a sample buffer 231 int numPictures = (data->num_pictures > 1) ? 2 : 1; 232 233 for (int index = 0; index < numPictures; index++) { 234 status = decodePicture(data, index); 235 if (status != DECODE_SUCCESS) { 236 endDecodingFrame(true); 237 return status; 238 } 239 } 240 241 if (mRangeMapped) { 242 updateDeblockedPicIndexes(frameType); 243 } 244 245 // let outputSurfaceBuffer handle "asReference" for VC1 246 status = outputSurfaceBuffer(); 247 return status; 248} 249 250 251Decode_Status VideoDecoderWMV::decodePicture(vbp_data_vc1 *data, int32_t picIndex) { 252 VAStatus vaStatus = VA_STATUS_SUCCESS; 253 Decode_Status status; 254 int32_t bufferIDCount = 0; 255 vbp_picture_data_vc1 *picData = &(data->pic_data[picIndex]); 256 VAPictureParameterBufferVC1 *picParams = picData->pic_parms; 257 258 if (picParams == NULL) { 259 return DECODE_PARSER_FAIL; 260 } 261 262 status = allocateVABufferIDs(picData->num_slices * 2 + 2); 263 CHECK_STATUS("allocateVABufferIDs"); 264 265 status = setReference(picParams, picIndex, mAcquiredBuffer->renderBuffer.surface); 266 CHECK_STATUS("setReference"); 267 268 if (mRangeMapped) { 269 // keep the destination surface for the picture after decoding and in-loop filtering 270 picParams->inloop_decoded_picture = mExtraSurfaces[mDeblockedCurrPicIndex]; 271 } else { 272 picParams->inloop_decoded_picture = VA_INVALID_SURFACE; 273 } 274 275 vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface); 276 CHECK_VA_STATUS("vaBeginPicture"); 277 // setting mDecodingFrame to true so vaEndPicture will be invoked to end the picture decoding. 278 mDecodingFrame = true; 279 280 vaStatus = vaCreateBuffer( 281 mVADisplay, 282 mVAContext, 283 VAPictureParameterBufferType, 284 sizeof(VAPictureParameterBufferVC1), 285 1, 286 picParams, 287 &mBufferIDs[bufferIDCount]); 288 CHECK_VA_STATUS("vaCreatePictureParameterBuffer"); 289 bufferIDCount++; 290 291 if (picParams->bitplane_present.value) { 292 vaStatus = vaCreateBuffer( 293 mVADisplay, 294 mVAContext, 295 VABitPlaneBufferType, 296 picData->size_bitplanes, 297 1, 298 picData->packed_bitplanes, 299 &mBufferIDs[bufferIDCount]); 300 CHECK_VA_STATUS("vaCreateBitPlaneBuffer"); 301 bufferIDCount++; 302 } 303 304 for (uint32_t i = 0; i < picData->num_slices; i++) { 305 vaStatus = vaCreateBuffer( 306 mVADisplay, 307 mVAContext, 308 VASliceParameterBufferType, 309 sizeof(VASliceParameterBufferVC1), 310 1, 311 &(picData->slc_data[i].slc_parms), 312 &mBufferIDs[bufferIDCount]); 313 CHECK_VA_STATUS("vaCreateSliceParameterBuffer"); 314 bufferIDCount++; 315 316 vaStatus = vaCreateBuffer( 317 mVADisplay, 318 mVAContext, 319 VASliceDataBufferType, 320 //size 321 picData->slc_data[i].slice_size, 322 //num_elements 323 1, 324 //slice data buffer pointer 325 //Note that this is the original data buffer ptr; 326 // offset to the actual slice data is provided in 327 // slice_data_offset in VASliceParameterBufferVC1 328 picData->slc_data[i].buffer_addr + picData->slc_data[i].slice_offset, 329 &mBufferIDs[bufferIDCount]); 330 CHECK_VA_STATUS("vaCreateSliceDataBuffer"); 331 bufferIDCount++; 332 } 333 334 vaStatus = vaRenderPicture( 335 mVADisplay, 336 mVAContext, 337 mBufferIDs, 338 bufferIDCount); 339 CHECK_VA_STATUS("vaRenderPicture"); 340 341 vaStatus = vaEndPicture(mVADisplay, mVAContext); 342 mDecodingFrame = false; 343 CHECK_VA_STATUS("vaRenderPicture"); 344 345 return DECODE_SUCCESS; 346} 347 348 349Decode_Status VideoDecoderWMV::setReference( 350 VAPictureParameterBufferVC1 *params, 351 int32_t picIndex, 352 VASurfaceID current) { 353 int frameType = params->picture_fields.bits.picture_type; 354 switch (frameType) { 355 case VC1_PTYPE_I: 356 params->forward_reference_picture = current; 357 params->backward_reference_picture = current; 358 break; 359 case VC1_PTYPE_P: 360 // check REFDIST in the picture parameter buffer 361 if (0 != params->reference_fields.bits.reference_distance_flag && 362 0 != params->reference_fields.bits.reference_distance) { 363 /* The previous decoded frame (distance is up to 16 but not 0) is used 364 for reference. Not supported here. 365 */ 366 return DECODE_NO_REFERENCE; 367 } 368 if (1 == picIndex) { 369 // handle interlace field coding case 370 if (1 == params->reference_fields.bits.num_reference_pictures || 371 1 == params->reference_fields.bits.reference_field_pic_indicator) { 372 /* 373 two reference fields or the second closest I/P field is used for 374 prediction. Set forward reference picture to INVALID so it will be 375 updated to a valid previous reconstructed reference frame later. 376 */ 377 params->forward_reference_picture = VA_INVALID_SURFACE; 378 } else { 379 /* the closest I/P is used for reference so it must be the 380 complementary field in the same surface. 381 */ 382 params->forward_reference_picture = current; 383 } 384 } 385 if (VA_INVALID_SURFACE == params->forward_reference_picture) { 386 if (mLastReference == NULL) { 387 return DECODE_NO_REFERENCE; 388 } 389 params->forward_reference_picture = mLastReference->renderBuffer.surface; 390 } 391 params->backward_reference_picture = VA_INVALID_SURFACE; 392 break; 393 case VC1_PTYPE_B: 394 if (mForwardReference == NULL || mLastReference == NULL) { 395 return DECODE_NO_REFERENCE; 396 } 397 params->forward_reference_picture = mForwardReference->renderBuffer.surface; 398 params->backward_reference_picture = mLastReference->renderBuffer.surface; 399 break; 400 case VC1_PTYPE_BI: 401 params->forward_reference_picture = VA_INVALID_SURFACE; 402 params->backward_reference_picture = VA_INVALID_SURFACE; 403 break; 404 case VC1_PTYPE_SKIPPED: 405 //Will never happen here 406 break; 407 default: 408 break; 409 } 410 return DECODE_SUCCESS; 411} 412 413void VideoDecoderWMV::updateDeblockedPicIndexes(int frameType) { 414 int32_t curPicIndex = mDeblockedCurrPicIndex; 415 416 /* Out Loop (range map) buffers */ 417 if (frameType != VC1_PTYPE_SKIPPED) { 418 if ((frameType == VC1_PTYPE_I) || (frameType == VC1_PTYPE_P)) { 419 mDeblockedCurrPicIndex = mDeblockedLastPicIndex; 420 mDeblockedLastPicIndex = curPicIndex; 421 } else { 422 mDeblockedCurrPicIndex = mDeblockedForwardPicIndex; 423 mDeblockedForwardPicIndex = curPicIndex; 424 } 425 } 426} 427 428Decode_Status VideoDecoderWMV::updateConfigData( 429 uint8_t *configData, 430 int32_t configDataLen, 431 uint8_t **newConfigData, 432 int32_t* newConfigDataLen) { 433 int32_t i = 0; 434 uint8_t *p = configData; 435 436 /* Check for start codes. If one exist, then this is VC-1 and not WMV. */ 437 while (i < configDataLen - 2) { 438 if ((p[i] == 0) && 439 (p[i + 1] == 0) && 440 (p[i + 2] == 1)) { 441 *newConfigData = NULL; 442 *newConfigDataLen = 0; 443 return DECODE_SUCCESS; 444 } 445 i++; 446 } 447 448 *newConfigDataLen = configDataLen + 9; 449 p = *newConfigData = new uint8_t [*newConfigDataLen]; 450 if (!p) { 451 return DECODE_MEMORY_FAIL; 452 } 453 454 /* If we get here we have 4+ bytes of codec data that must be formatted */ 455 /* to pass through as an RCV sequence header. */ 456 p[0] = 0; 457 p[1] = 0; 458 p[2] = 1; 459 p[3] = 0x0f; /* Start code. */ 460 p[4] = (mVideoFormatInfo.width >> 8) & 0x0ff; 461 p[5] = mVideoFormatInfo.width & 0x0ff; 462 p[6] = (mVideoFormatInfo.height >> 8) & 0x0ff; 463 p[7] = mVideoFormatInfo.height & 0x0ff; 464 465 memcpy(p + 8, configData, configDataLen); 466 *(p + configDataLen + 8) = 0x80; 467 468 return DECODE_SUCCESS; 469} 470 471Decode_Status VideoDecoderWMV::startVA(vbp_data_vc1 *data) { 472 updateFormatInfo(data); 473 474 VAProfile vaProfile; 475 switch (data->se_data->PROFILE) { 476 case 0: 477 vaProfile = VAProfileVC1Simple; 478 break; 479 case 1: 480 vaProfile = VAProfileVC1Main; 481 break; 482 default: 483 vaProfile = VAProfileVC1Advanced; 484 break; 485 } 486 487 return VideoDecoderBase::setupVA(VC1_SURFACE_NUMBER, vaProfile, VC1_EXTRA_SURFACE_NUMBER); 488} 489 490void VideoDecoderWMV::updateFormatInfo(vbp_data_vc1 *data) { 491 ITRACE("updateFormatInfo: current size: %d x %d, new size: %d x %d", 492 mVideoFormatInfo.width, mVideoFormatInfo.height, 493 data->se_data->CODED_WIDTH, data->se_data->CODED_HEIGHT); 494 495 mVideoFormatInfo.cropBottom = data->se_data->CODED_HEIGHT > mVideoFormatInfo.height ? 496 data->se_data->CODED_HEIGHT - mVideoFormatInfo.height : 0; 497 mVideoFormatInfo.cropRight = data->se_data->CODED_WIDTH > mVideoFormatInfo.width ? 498 data->se_data->CODED_WIDTH - mVideoFormatInfo.width : 0; 499 500 if ((mVideoFormatInfo.width != data->se_data->CODED_WIDTH || 501 mVideoFormatInfo.height != data->se_data->CODED_HEIGHT) && 502 data->se_data->CODED_WIDTH && 503 data->se_data->CODED_HEIGHT) { 504 // encoded image size 505 mVideoFormatInfo.width = data->se_data->CODED_WIDTH; 506 mVideoFormatInfo.height = data->se_data->CODED_HEIGHT; 507 mSizeChanged = true; 508 ITRACE("Video size is changed."); 509 } 510 511 // video_range has default value of 0. Y ranges from 16 to 235. 512 mVideoFormatInfo.videoRange = 0; 513 514 switch (data->se_data->MATRIX_COEF) { 515 case 1: 516 mVideoFormatInfo.colorMatrix = VA_SRC_BT709; 517 break; 518 // ITU-R BT.1700, ITU-R BT.601-5, and SMPTE 293M-1996. 519 case 6: 520 mVideoFormatInfo.colorMatrix = VA_SRC_BT601; 521 break; 522 default: 523 // unknown color matrix, set to 0 so color space flag will not be set. 524 mVideoFormatInfo.colorMatrix = 0; 525 break; 526 } 527 528 mVideoFormatInfo.aspectX = data->se_data->ASPECT_HORIZ_SIZE; 529 mVideoFormatInfo.aspectY = data->se_data->ASPECT_VERT_SIZE; 530 mVideoFormatInfo.bitrate = 0; //data->se_data->bitrate; 531 mVideoFormatInfo.valid = true; 532 533 setRenderRect(); 534 setColorSpaceInfo(mVideoFormatInfo.colorMatrix, mVideoFormatInfo.videoRange); 535} 536 537Decode_Status VideoDecoderWMV::allocateVABufferIDs(int32_t number) { 538 if (mNumBufferIDs > number) { 539 return DECODE_SUCCESS; 540 } 541 if (mBufferIDs) { 542 delete [] mBufferIDs; 543 } 544 mBufferIDs = NULL; 545 mNumBufferIDs = 0; 546 mBufferIDs = new VABufferID [number]; 547 if (mBufferIDs == NULL) { 548 return DECODE_MEMORY_FAIL; 549 } 550 mNumBufferIDs = number; 551 return DECODE_SUCCESS; 552} 553 554Decode_Status VideoDecoderWMV::parseBuffer(uint8_t *data, int32_t size, vbp_data_vc1 **vbpData) { 555 Decode_Status status; 556 557 if (data == NULL || size == 0) { 558 return DECODE_INVALID_DATA; 559 } 560 561 if (mConfigDataParsed) { 562 status = VideoDecoderBase::parseBuffer(data, size, false, (void**)vbpData); 563 CHECK_STATUS("VideoDecoderBase::parseBuffer"); 564 } else { 565 uint8_t *newData = NULL; 566 int32_t newSize = 0; 567 status = updateConfigData(data, size, &newData, &newSize); 568 CHECK_STATUS("updateConfigData"); 569 570 if (newSize) { 571 status = VideoDecoderBase::parseBuffer(newData, newSize, true, (void**)vbpData); 572 delete [] newData; 573 } else { 574 status = VideoDecoderBase::parseBuffer(data, size, true, (void**)vbpData); 575 } 576 CHECK_STATUS("VideoDecoderBase::parseBuffer"); 577 mConfigDataParsed = true; 578 } 579 return DECODE_SUCCESS; 580} 581 582 583Decode_Status VideoDecoderWMV::checkHardwareCapability() { 584#ifndef USE_GEN_HW 585 VAStatus vaStatus; 586 VAConfigAttrib cfgAttribs[2]; 587 cfgAttribs[0].type = VAConfigAttribMaxPictureWidth; 588 cfgAttribs[1].type = VAConfigAttribMaxPictureHeight; 589 vaStatus = vaGetConfigAttributes(mVADisplay, VAProfileVC1Advanced, 590 VAEntrypointVLD, cfgAttribs, 2); 591 CHECK_VA_STATUS("vaGetConfigAttributes"); 592 if (cfgAttribs[0].value * cfgAttribs[1].value < (uint32_t)mVideoFormatInfo.width * (uint32_t)mVideoFormatInfo.height) { 593 ETRACE("hardware supports resolution %d * %d smaller than the clip resolution %d * %d", 594 cfgAttribs[0].value, cfgAttribs[1].value, mVideoFormatInfo.width, mVideoFormatInfo.height); 595 return DECODE_DRIVER_FAIL; 596 } 597#endif 598 return DECODE_SUCCESS; 599} 600 601 602