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