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 "VideoDecoderVP8.h" 18 #include "VideoDecoderTrace.h" 19 #include <string.h> 20 21 #define MAX_PICTURE_WIDTH_VP8 1920 22 #define MAX_PICTURE_HEIGHT_VP8 1088 23 24 VideoDecoderVP8::VideoDecoderVP8(const char *mimeType) 25 : VideoDecoderBase(mimeType, VBP_VP8) { 26 invalidateReferenceFrames(0); 27 invalidateReferenceFrames(1); 28 } 29 30 VideoDecoderVP8::~VideoDecoderVP8() { 31 stop(); 32 } 33 34 void VideoDecoderVP8::invalidateReferenceFrames(int toggle) { 35 ReferenceFrameBuffer *p = mRFBs[toggle]; 36 for (int i = 0; i < VP8_REF_SIZE; i++) { 37 p->index = (uint32_t) -1; 38 p->surfaceBuffer = NULL; 39 p++; 40 } 41 } 42 43 void VideoDecoderVP8::clearAsReference(int toggle, int ref_type) { 44 ReferenceFrameBuffer ref = mRFBs[toggle][ref_type]; 45 if (ref.surfaceBuffer) { 46 ref.surfaceBuffer->asReferernce = false; 47 } 48 } 49 50 void VideoDecoderVP8::updateFormatInfo(vbp_data_vp8 *data) { 51 uint32_t width = data->codec_data->frame_width; 52 uint32_t height = data->codec_data->frame_height; 53 ITRACE("updateFormatInfo: current size: %d x %d, new size: %d x %d", 54 mVideoFormatInfo.width, mVideoFormatInfo.height, width, height); 55 56 if ((mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER) && mStoreMetaData) { 57 pthread_mutex_lock(&mFormatLock); 58 } 59 60 if ((mVideoFormatInfo.width != width || 61 mVideoFormatInfo.height != height) && 62 width && height) { 63 if ((VideoDecoderBase::alignMB(mVideoFormatInfo.width) != width) || 64 (VideoDecoderBase::alignMB(mVideoFormatInfo.height) != height)) { 65 mSizeChanged = true; 66 ITRACE("Video size is changed."); 67 } 68 mVideoFormatInfo.width = width; 69 mVideoFormatInfo.height = height; 70 } 71 72 // video_range has default value of 0. Y ranges from 16 to 235. 73 mVideoFormatInfo.videoRange = 0; 74 75 switch (data->codec_data->clr_type) { 76 case 0: 77 mVideoFormatInfo.colorMatrix = VA_SRC_BT601; 78 break; 79 case 1: 80 default: 81 mVideoFormatInfo.colorMatrix = 0; 82 break; 83 } 84 85 mVideoFormatInfo.cropLeft = data->codec_data->crop_left; 86 mVideoFormatInfo.cropRight = data->codec_data->crop_right; 87 mVideoFormatInfo.cropTop = data->codec_data->crop_top; 88 mVideoFormatInfo.cropBottom = data->codec_data->crop_bottom; 89 ITRACE("Cropping: left = %d, top = %d, right = %d, bottom = %d", data->codec_data->crop_left, data->codec_data->crop_top, data->codec_data->crop_right, data->codec_data->crop_bottom); 90 91 if ((mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER) && mStoreMetaData) { 92 if (mSizeChanged) { 93 mVideoFormatInfo.valid = false; 94 } else { 95 mVideoFormatInfo.valid = true; 96 } 97 98 pthread_mutex_unlock(&mFormatLock); 99 } else { 100 mVideoFormatInfo.valid = true; 101 } 102 103 setRenderRect(); 104 setColorSpaceInfo(mVideoFormatInfo.colorMatrix, mVideoFormatInfo.videoRange); 105 } 106 107 Decode_Status VideoDecoderVP8::startVA(vbp_data_vp8 *data) { 108 updateFormatInfo(data); 109 110 VAProfile vaProfile = VAProfileVP8Version0_3; 111 if (data->codec_data->version_num > 3) { 112 return DECODE_PARSER_FAIL; 113 } 114 115 enableLowDelayMode(true); 116 117 return VideoDecoderBase::setupVA(VP8_SURFACE_NUMBER + VP8_REF_SIZE, vaProfile); 118 } 119 120 Decode_Status VideoDecoderVP8::start(VideoConfigBuffer *buffer) { 121 Decode_Status status; 122 123 status = VideoDecoderBase::start(buffer); 124 CHECK_STATUS("VideoDecoderBase::start"); 125 126 // We don't want base class to manage reference. 127 VideoDecoderBase::ManageReference(false); 128 129 if (buffer->data == NULL || buffer->size == 0) { 130 WTRACE("No config data to start VA."); 131 return DECODE_SUCCESS; 132 } 133 134 vbp_data_vp8 *data = NULL; 135 status = VideoDecoderBase::parseBuffer(buffer->data, buffer->size, true, (void**)&data); 136 CHECK_STATUS("VideoDecoderBase::parseBuffer"); 137 138 if (data->codec_data->frame_width > MAX_PICTURE_WIDTH_VP8 || 139 data->codec_data->frame_height > MAX_PICTURE_HEIGHT_VP8) { 140 return DECODE_INVALID_DATA; 141 } 142 143 status = startVA(data); 144 return status; 145 } 146 147 void VideoDecoderVP8::stop(void) { 148 VideoDecoderBase::stop(); 149 150 invalidateReferenceFrames(0); 151 invalidateReferenceFrames(1); 152 } 153 154 void VideoDecoderVP8::flush(void) { 155 VideoDecoderBase::flush(); 156 157 invalidateReferenceFrames(0); 158 invalidateReferenceFrames(1); 159 } 160 161 Decode_Status VideoDecoderVP8::decode(VideoDecodeBuffer *buffer) { 162 Decode_Status status; 163 vbp_data_vp8 *data = NULL; 164 if (buffer == NULL) { 165 ETRACE("VideoDecodeBuffer is NULL."); 166 return DECODE_INVALID_DATA; 167 } 168 169 status = VideoDecoderBase::parseBuffer( 170 buffer->data, 171 buffer->size, 172 false, 173 (void**)&data); 174 CHECK_STATUS("VideoDecoderBase::parseBuffer"); 175 176 if (data->codec_data->frame_width > MAX_PICTURE_WIDTH_VP8 || 177 data->codec_data->frame_height > MAX_PICTURE_HEIGHT_VP8) { 178 return DECODE_INVALID_DATA; 179 } 180 181 mShowFrame = data->codec_data->show_frame; 182 183 if (!mVAStarted) { 184 status = startVA(data); 185 CHECK_STATUS("startVA"); 186 } 187 188 VideoDecoderBase::setRotationDegrees(buffer->rotationDegrees); 189 190 status = decodeFrame(buffer, data); 191 192 return status; 193 } 194 195 Decode_Status VideoDecoderVP8::decodeFrame(VideoDecodeBuffer* buffer, vbp_data_vp8 *data) { 196 Decode_Status status; 197 bool useGraphicbuffer = mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER; 198 mCurrentPTS = buffer->timeStamp; 199 if (0 == data->num_pictures || NULL == data->pic_data) { 200 WTRACE("Number of pictures is 0."); 201 return DECODE_SUCCESS; 202 } 203 204 if (VP8_KEY_FRAME == data->codec_data->frame_type) { 205 updateFormatInfo(data); 206 if (mSizeChanged && !(mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER)) { 207 mSizeChanged = false; 208 return DECODE_FORMAT_CHANGE; 209 } 210 211 bool needFlush = false; 212 if (useGraphicbuffer) { 213 // For VP8 in adaptive playback legacy mode, 214 // force buffer reallocation. 215 needFlush = mSizeChanged; 216 } 217 if (needFlush) { 218 if (mStoreMetaData) { 219 status = endDecodingFrame(false); 220 CHECK_STATUS("endDecodingFrame"); 221 } else { 222 flushSurfaceBuffers(); 223 } 224 mSizeChanged = false; 225 return DECODE_FORMAT_CHANGE; 226 } 227 } 228 229 if (data->codec_data->frame_type == VP8_SKIPPED_FRAME) { 230 // Do nothing for skip frame as the last frame will be rendered agian by natively 231 return DECODE_SUCCESS; 232 } 233 234 status = acquireSurfaceBuffer(); 235 CHECK_STATUS("acquireSurfaceBuffer"); 236 237 // set referenceFrame to true if frame decoded is I/P frame, false otherwise. 238 int frameType = data->codec_data->frame_type; 239 mAcquiredBuffer->referenceFrame = (frameType == VP8_KEY_FRAME || frameType == VP8_INTER_FRAME); 240 // assume it is frame picture. 241 mAcquiredBuffer->renderBuffer.scanFormat = VA_FRAME_PICTURE; 242 mAcquiredBuffer->renderBuffer.timeStamp = buffer->timeStamp; 243 mAcquiredBuffer->renderBuffer.flag = 0; 244 if (buffer->flag & WANT_DECODE_ONLY) { 245 mAcquiredBuffer->renderBuffer.flag |= WANT_DECODE_ONLY; 246 } 247 if (mSizeChanged) { 248 mSizeChanged = false; 249 mAcquiredBuffer->renderBuffer.flag |= IS_RESOLUTION_CHANGE; 250 } 251 252 // Here data->num_pictures is always equal to 1 253 for (uint32_t index = 0; index < data->num_pictures; index++) { 254 status = decodePicture(data, index); 255 if (status != DECODE_SUCCESS) { 256 endDecodingFrame(true); 257 return status; 258 } 259 } 260 261 if (frameType != VP8_SKIPPED_FRAME) { 262 updateReferenceFrames(data); 263 } 264 265 // if sample is successfully decoded, call outputSurfaceBuffer(); otherwise 266 // call releaseSurfacebuffer(); 267 status = outputSurfaceBuffer(); 268 return status; 269 } 270 271 Decode_Status VideoDecoderVP8::decodePicture(vbp_data_vp8 *data, int32_t picIndex) { 272 VAStatus vaStatus = VA_STATUS_SUCCESS; 273 Decode_Status status; 274 uint32_t bufferIDCount = 0; 275 VABufferID bufferIDs[5]; 276 277 vbp_picture_data_vp8 *picData = &(data->pic_data[picIndex]); 278 VAPictureParameterBufferVP8 *picParams = picData->pic_parms; 279 280 status = setReference(picParams); 281 CHECK_STATUS("setReference"); 282 283 vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface); 284 CHECK_VA_STATUS("vaBeginPicture"); 285 // setting mDecodingFrame to true so vaEndPicture will be invoked to end the picture decoding. 286 mDecodingFrame = true; 287 288 vaStatus = vaCreateBuffer( 289 mVADisplay, 290 mVAContext, 291 VAPictureParameterBufferType, 292 sizeof(VAPictureParameterBufferVP8), 293 1, 294 picParams, 295 &bufferIDs[bufferIDCount]); 296 CHECK_VA_STATUS("vaCreatePictureParameterBuffer"); 297 bufferIDCount++; 298 299 vaStatus = vaCreateBuffer( 300 mVADisplay, 301 mVAContext, 302 VAProbabilityBufferType, 303 sizeof(VAProbabilityDataBufferVP8), 304 1, 305 data->prob_data, 306 &bufferIDs[bufferIDCount]); 307 CHECK_VA_STATUS("vaCreateProbabilityBuffer"); 308 bufferIDCount++; 309 310 vaStatus = vaCreateBuffer( 311 mVADisplay, 312 mVAContext, 313 VAIQMatrixBufferType, 314 sizeof(VAIQMatrixBufferVP8), 315 1, 316 data->IQ_matrix_buf, 317 &bufferIDs[bufferIDCount]); 318 CHECK_VA_STATUS("vaCreateIQMatrixBuffer"); 319 bufferIDCount++; 320 321 /* Here picData->num_slices is always equal to 1 */ 322 for (uint32_t i = 0; i < picData->num_slices; i++) { 323 vaStatus = vaCreateBuffer( 324 mVADisplay, 325 mVAContext, 326 VASliceParameterBufferType, 327 sizeof(VASliceParameterBufferVP8), 328 1, 329 &(picData->slc_data[i].slc_parms), 330 &bufferIDs[bufferIDCount]); 331 CHECK_VA_STATUS("vaCreateSliceParameterBuffer"); 332 bufferIDCount++; 333 334 vaStatus = vaCreateBuffer( 335 mVADisplay, 336 mVAContext, 337 VASliceDataBufferType, 338 picData->slc_data[i].slice_size, //size 339 1, //num_elements 340 picData->slc_data[i].buffer_addr + picData->slc_data[i].slice_offset, 341 &bufferIDs[bufferIDCount]); 342 CHECK_VA_STATUS("vaCreateSliceDataBuffer"); 343 bufferIDCount++; 344 } 345 346 vaStatus = vaRenderPicture( 347 mVADisplay, 348 mVAContext, 349 bufferIDs, 350 bufferIDCount); 351 CHECK_VA_STATUS("vaRenderPicture"); 352 353 vaStatus = vaEndPicture(mVADisplay, mVAContext); 354 mDecodingFrame = false; 355 CHECK_VA_STATUS("vaEndPicture"); 356 357 return DECODE_SUCCESS; 358 } 359 360 Decode_Status VideoDecoderVP8::setReference(VAPictureParameterBufferVP8 *picParam) { 361 int frameType = picParam->pic_fields.bits.key_frame; 362 switch (frameType) { 363 case VP8_KEY_FRAME: 364 picParam->last_ref_frame = VA_INVALID_SURFACE; 365 picParam->alt_ref_frame = VA_INVALID_SURFACE; 366 picParam->golden_ref_frame = VA_INVALID_SURFACE; 367 break; 368 case VP8_INTER_FRAME: 369 if (mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer == NULL || 370 mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer == NULL || 371 mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer == NULL) { 372 mAcquiredBuffer->renderBuffer.errBuf.errorNumber = 1; 373 mAcquiredBuffer->renderBuffer.errBuf.errorArray[0].type = DecodeRefMissing; 374 return DECODE_NO_REFERENCE; 375 } 376 //mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer = mLastReference; 377 picParam->last_ref_frame = mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer->renderBuffer.surface; 378 picParam->alt_ref_frame = mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer->renderBuffer.surface; 379 picParam->golden_ref_frame = mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer->renderBuffer.surface; 380 break; 381 case VP8_SKIPPED_FRAME: 382 // will never happen here 383 break; 384 default: 385 return DECODE_PARSER_FAIL; 386 } 387 388 return DECODE_SUCCESS; 389 } 390 391 void VideoDecoderVP8::updateReferenceFrames(vbp_data_vp8 *data) { 392 /* Refresh last frame reference buffer using the currently reconstructed frame */ 393 refreshLastReference(data); 394 395 /* Refresh golden frame reference buffer using the currently reconstructed frame */ 396 refreshGoldenReference(data); 397 398 /* Refresh alternative frame reference buffer using the currently reconstructed frame */ 399 refreshAltReference(data); 400 401 /* Update reference frames */ 402 for (int i = 0; i < VP8_REF_SIZE; i++) { 403 VideoSurfaceBuffer *p = mRFBs[1][i].surfaceBuffer; 404 int j; 405 for (j = 0; j < VP8_REF_SIZE; j++) { 406 if (p == mRFBs[0][j].surfaceBuffer) { 407 break; 408 } 409 } 410 if (j == VP8_REF_SIZE) { 411 clearAsReference(1, i); 412 } 413 } 414 } 415 416 void VideoDecoderVP8::refreshLastReference(vbp_data_vp8 *data) { 417 /* Save previous last reference */ 418 mRFBs[1][VP8_LAST_REF_PIC].surfaceBuffer = mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer; 419 mRFBs[1][VP8_LAST_REF_PIC].index = mRFBs[0][VP8_LAST_REF_PIC].index; 420 421 /* For key frame, this is always true */ 422 if (data->codec_data->refresh_last_frame) { 423 mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer = mAcquiredBuffer; 424 mRFBs[0][VP8_LAST_REF_PIC].index = mAcquiredBuffer->renderBuffer.surface; 425 mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer->asReferernce = true; 426 } 427 } 428 429 void VideoDecoderVP8::refreshGoldenReference(vbp_data_vp8 *data) { 430 /* Save previous golden reference */ 431 mRFBs[1][VP8_GOLDEN_REF_PIC].surfaceBuffer = mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer; 432 mRFBs[1][VP8_GOLDEN_REF_PIC].index = mRFBs[0][VP8_GOLDEN_REF_PIC].index; 433 434 if (data->codec_data->golden_copied != BufferCopied_NoneToGolden) { 435 if (data->codec_data->golden_copied == BufferCopied_LastToGolden) { 436 /* LastFrame is copied to GoldenFrame */ 437 mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer = mRFBs[1][VP8_LAST_REF_PIC].surfaceBuffer; 438 mRFBs[0][VP8_GOLDEN_REF_PIC].index = mRFBs[1][VP8_LAST_REF_PIC].index; 439 } else if (data->codec_data->golden_copied == BufferCopied_AltRefToGolden) { 440 /* AltRefFrame is copied to GoldenFrame */ 441 mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer = mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer; 442 mRFBs[0][VP8_GOLDEN_REF_PIC].index = mRFBs[0][VP8_ALT_REF_PIC].index; 443 } 444 } 445 446 /* For key frame, this is always true */ 447 if (data->codec_data->refresh_golden_frame) { 448 mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer = mAcquiredBuffer; 449 mRFBs[0][VP8_GOLDEN_REF_PIC].index = mAcquiredBuffer->renderBuffer.surface; 450 mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer->asReferernce = true; 451 } 452 } 453 454 void VideoDecoderVP8::refreshAltReference(vbp_data_vp8 *data) { 455 /* Save previous alternative reference */ 456 mRFBs[1][VP8_ALT_REF_PIC].surfaceBuffer = mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer; 457 mRFBs[1][VP8_ALT_REF_PIC].index = mRFBs[0][VP8_ALT_REF_PIC].index; 458 459 if (data->codec_data->altref_copied != BufferCopied_NoneToAltRef) { 460 if (data->codec_data->altref_copied == BufferCopied_LastToAltRef) { 461 /* LastFrame is copied to AltRefFrame */ 462 mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer = mRFBs[1][VP8_LAST_REF_PIC].surfaceBuffer; 463 mRFBs[0][VP8_ALT_REF_PIC].index = mRFBs[1][VP8_LAST_REF_PIC].index; 464 } else if (data->codec_data->altref_copied == BufferCopied_GoldenToAltRef) { 465 /* GoldenFrame is copied to AltRefFrame */ 466 mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer = mRFBs[1][VP8_GOLDEN_REF_PIC].surfaceBuffer; 467 mRFBs[0][VP8_ALT_REF_PIC].index = mRFBs[1][VP8_GOLDEN_REF_PIC].index; 468 } 469 } 470 471 /* For key frame, this is always true */ 472 if (data->codec_data->refresh_alt_frame) { 473 mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer = mAcquiredBuffer; 474 mRFBs[0][VP8_ALT_REF_PIC].index = mAcquiredBuffer->renderBuffer.surface; 475 mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer->asReferernce = true; 476 } 477 } 478 479 480 Decode_Status VideoDecoderVP8::checkHardwareCapability() { 481 VAStatus vaStatus; 482 VAConfigAttrib cfgAttribs[2]; 483 cfgAttribs[0].type = VAConfigAttribMaxPictureWidth; 484 cfgAttribs[1].type = VAConfigAttribMaxPictureHeight; 485 vaStatus = vaGetConfigAttributes(mVADisplay, VAProfileVP8Version0_3, 486 VAEntrypointVLD, cfgAttribs, 2); 487 CHECK_VA_STATUS("vaGetConfigAttributes"); 488 if (cfgAttribs[0].value * cfgAttribs[1].value < (uint32_t)mVideoFormatInfo.width * (uint32_t)mVideoFormatInfo.height) { 489 ETRACE("hardware supports resolution %d * %d smaller than the clip resolution %d * %d", 490 cfgAttribs[0].value, cfgAttribs[1].value, mVideoFormatInfo.width, mVideoFormatInfo.height); 491 return DECODE_DRIVER_FAIL; 492 } 493 494 return DECODE_SUCCESS; 495 } 496 497