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