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