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 "VideoDecoderMPEG2.h" 18 #include "VideoDecoderTrace.h" 19 #include <string.h> 20 21 #define MAX_PICTURE_WIDTH_MPEG2 1920 22 #define MAX_PICTURE_HEIGHT_MPEG2 1088 23 24 VideoDecoderMPEG2::VideoDecoderMPEG2(const char *mimeType) 25 : VideoDecoderBase(mimeType, VBP_MPEG2), 26 mBufferIDs(NULL), 27 mNumBufferIDs(0) { 28 //do nothing 29 } 30 31 VideoDecoderMPEG2::~VideoDecoderMPEG2() { 32 stop(); 33 } 34 35 Decode_Status VideoDecoderMPEG2::start(VideoConfigBuffer *buffer) { 36 Decode_Status status; 37 38 status = VideoDecoderBase::start(buffer); 39 CHECK_STATUS("VideoDecoderBase::start"); 40 41 if (buffer->data == NULL || buffer->size == 0) { 42 WTRACE("No config data to start VA."); 43 return DECODE_SUCCESS; 44 } 45 46 vbp_data_mpeg2 *data = NULL; 47 status = VideoDecoderBase::parseBuffer( 48 buffer->data, 49 buffer->size, 50 true, // config flag 51 (void**)&data); 52 CHECK_STATUS("VideoDecoderBase::parseBuffer"); 53 54 if (data->codec_data->frame_width > MAX_PICTURE_WIDTH_MPEG2 || 55 data->codec_data->frame_height > MAX_PICTURE_HEIGHT_MPEG2) { 56 return DECODE_INVALID_DATA; 57 } 58 59 status = startVA(data); 60 return status; 61 } 62 63 void VideoDecoderMPEG2::stop(void) { 64 if (mBufferIDs) { 65 delete [] mBufferIDs; 66 mBufferIDs = NULL; 67 } 68 mNumBufferIDs = 0; 69 70 VideoDecoderBase::stop(); 71 } 72 73 Decode_Status VideoDecoderMPEG2::decode(VideoDecodeBuffer *buffer) { 74 Decode_Status status; 75 vbp_data_mpeg2 *data = NULL; 76 bool useGraphicbuffer = mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER; 77 78 if (buffer == NULL) { 79 return DECODE_INVALID_DATA; 80 } 81 82 #ifdef DUMP_INPUT_BUFFER 83 if (mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER) { 84 DumpInputBuffer(buffer, "mpeg2"); 85 } 86 #endif 87 88 buffer->ext = NULL; 89 status = VideoDecoderBase::parseBuffer( 90 buffer->data, 91 buffer->size, 92 false, // config flag 93 (void**)&data); 94 CHECK_STATUS("VideoDecoderBase::parseBuffer"); 95 96 if (data->codec_data->frame_width > MAX_PICTURE_WIDTH_MPEG2 || 97 data->codec_data->frame_height > MAX_PICTURE_HEIGHT_MPEG2) { 98 return DECODE_INVALID_DATA; 99 } 100 101 if (!mVAStarted) { 102 status = startVA(data); 103 CHECK_STATUS("startVA"); 104 } 105 106 if (mSizeChanged && !useGraphicbuffer) { 107 // some container has the incorrect width/height. 108 // send the format change to OMX to update the crop info. 109 mSizeChanged = false; 110 ITRACE("Video size is changed during startVA"); 111 return DECODE_FORMAT_CHANGE; 112 } 113 114 if ((mVideoFormatInfo.width != (uint32_t)data->codec_data->frame_width || 115 mVideoFormatInfo.height != (uint32_t)data->codec_data->frame_height) && 116 (data->codec_data->frame_width > 0) && (data->codec_data->frame_height)) { 117 // update encoded image size 118 ITRACE("Video size is changed. from %dx%d to %dx%d\n",mVideoFormatInfo.width,mVideoFormatInfo.height, data->codec_data->frame_width,data->codec_data->frame_height); 119 if (useGraphicbuffer && mStoreMetaData) { 120 pthread_mutex_lock(&mFormatLock); 121 } 122 mVideoFormatInfo.width = data->codec_data->frame_width; 123 mVideoFormatInfo.height = data->codec_data->frame_height; 124 bool needFlush = false; 125 if (useGraphicbuffer) { 126 if (mStoreMetaData) { 127 needFlush = true; 128 129 mVideoFormatInfo.valid = false; 130 pthread_mutex_unlock(&mFormatLock); 131 } else { 132 needFlush = (mVideoFormatInfo.width > mVideoFormatInfo.surfaceWidth) 133 || (mVideoFormatInfo.height > mVideoFormatInfo.surfaceHeight); 134 } 135 } 136 137 if (needFlush) { 138 if (mStoreMetaData) { 139 status = endDecodingFrame(false); 140 CHECK_STATUS("endDecodingFrame"); 141 } else { 142 flushSurfaceBuffers(); 143 } 144 mSizeChanged = false; 145 return DECODE_FORMAT_CHANGE; 146 } else { 147 mSizeChanged = true; 148 } 149 150 setRenderRect(); 151 } else { 152 if (useGraphicbuffer && mStoreMetaData) { 153 mVideoFormatInfo.valid = true; 154 } 155 } 156 157 VideoDecoderBase::setRotationDegrees(buffer->rotationDegrees); 158 159 status = decodeFrame(buffer, data); 160 CHECK_STATUS("decodeFrame"); 161 162 return status; 163 } 164 165 void VideoDecoderMPEG2::flush(void) { 166 VideoDecoderBase::flush(); 167 } 168 169 Decode_Status VideoDecoderMPEG2::decodeFrame(VideoDecodeBuffer *buffer, vbp_data_mpeg2 *data) { 170 Decode_Status status; 171 // check if any slice is parsed, we may just receive configuration data 172 if (data->num_pictures == 0 || data->pic_data == NULL) { 173 WTRACE("Number of pictures is 0, buffer contains configuration data only?"); 174 return DECODE_SUCCESS; 175 } 176 177 status = acquireSurfaceBuffer(); 178 CHECK_STATUS("acquireSurfaceBuffer"); 179 180 // set referenceFrame to true if frame decoded is I/P frame, false otherwise. 181 int frameType = data->codec_data->frame_type; 182 mAcquiredBuffer->referenceFrame = (frameType == MPEG2_PICTURE_TYPE_I || frameType == MPEG2_PICTURE_TYPE_P); 183 184 if (data->num_pictures > 1) { 185 if (data->pic_data[0].pic_parms->picture_coding_extension.bits.picture_structure == MPEG2_PIC_STRUCT_TOP) 186 { 187 mAcquiredBuffer->renderBuffer.scanFormat = VA_TOP_FIELD; 188 } else { 189 mAcquiredBuffer->renderBuffer.scanFormat = VA_BOTTOM_FIELD; 190 } 191 } else { 192 mAcquiredBuffer->renderBuffer.scanFormat = VA_FRAME_PICTURE; 193 } 194 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 for (uint32_t index = 0; index < data->num_pictures; index++) { 206 status = decodePicture(data, index); 207 if (status != DECODE_SUCCESS) { 208 endDecodingFrame(true); 209 return status; 210 } 211 } 212 213 // if sample is successfully decoded, call outputSurfaceBuffer(); otherwise 214 // call releaseSurfacebuffer(); 215 status = outputSurfaceBuffer(); 216 return status; 217 } 218 219 Decode_Status VideoDecoderMPEG2::decodePicture(vbp_data_mpeg2 *data, int picIndex) { 220 Decode_Status status; 221 VAStatus vaStatus; 222 uint32_t bufferIDCount = 0; 223 224 vbp_picture_data_mpeg2 *picData = &(data->pic_data[picIndex]); 225 VAPictureParameterBufferMPEG2 *picParam = picData->pic_parms; 226 227 status = allocateVABufferIDs(picData->num_slices * 2 + 2); 228 CHECK_STATUS("allocateVABufferIDs") 229 230 // send picture parametre for each slice 231 status = setReference(picParam); 232 CHECK_STATUS("setReference"); 233 234 vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface); 235 CHECK_VA_STATUS("vaBeginPicture"); 236 // setting mDecodingFrame to true so vaEndPicture will be invoked to end the picture decoding. 237 mDecodingFrame = true; 238 239 vaStatus = vaCreateBuffer( 240 mVADisplay, 241 mVAContext, 242 VAPictureParameterBufferType, 243 sizeof(VAPictureParameterBufferMPEG2), 244 1, 245 picParam, 246 &mBufferIDs[bufferIDCount]); 247 CHECK_VA_STATUS("vaCreatePictureParameterBuffer"); 248 bufferIDCount++; 249 250 vaStatus = vaCreateBuffer( 251 mVADisplay, 252 mVAContext, 253 VAIQMatrixBufferType, 254 sizeof(VAIQMatrixBufferMPEG2), 255 1, 256 data->iq_matrix_buffer, 257 &mBufferIDs[bufferIDCount]); 258 CHECK_VA_STATUS("vaCreateIQMatrixBuffer"); 259 bufferIDCount++; 260 261 for (uint32_t i = 0; i < picData->num_slices; i++) { 262 vaStatus = vaCreateBuffer( 263 mVADisplay, 264 mVAContext, 265 VASliceParameterBufferType, 266 sizeof(VASliceParameterBufferMPEG2), 267 1, 268 &(picData->slice_data[i].slice_param), 269 &mBufferIDs[bufferIDCount]); 270 CHECK_VA_STATUS("vaCreateSliceParameterBuffer"); 271 bufferIDCount++; 272 273 // slice data buffer pointer 274 // Note that this is the original data buffer ptr; 275 // offset to the actual slice data is provided in 276 // slice_data_offset in VASliceParameterBufferMPEG2 277 vaStatus = vaCreateBuffer( 278 mVADisplay, 279 mVAContext, 280 VASliceDataBufferType, 281 picData->slice_data[i].slice_size, //size 282 1, //num_elements 283 picData->slice_data[i].buffer_addr + picData->slice_data[i].slice_offset, 284 &mBufferIDs[bufferIDCount]); 285 CHECK_VA_STATUS("vaCreateSliceDataBuffer"); 286 bufferIDCount++; 287 } 288 289 vaStatus = vaRenderPicture( 290 mVADisplay, 291 mVAContext, 292 mBufferIDs, 293 bufferIDCount); 294 CHECK_VA_STATUS("vaRenderPicture"); 295 296 vaStatus = vaEndPicture(mVADisplay, mVAContext); 297 mDecodingFrame = false; 298 CHECK_VA_STATUS("vaRenderPicture"); 299 300 return DECODE_SUCCESS; 301 } 302 303 Decode_Status VideoDecoderMPEG2::setReference(VAPictureParameterBufferMPEG2 *picParam) { 304 switch (picParam->picture_coding_type) { 305 case MPEG2_PICTURE_TYPE_I: 306 picParam->forward_reference_picture = VA_INVALID_SURFACE; 307 picParam->backward_reference_picture = VA_INVALID_SURFACE; 308 break; 309 case MPEG2_PICTURE_TYPE_P: 310 if (mLastReference != NULL) { 311 picParam->forward_reference_picture = mLastReference->renderBuffer.surface; 312 } else { 313 VTRACE("%s: no reference frame, but keep decoding", __FUNCTION__); 314 picParam->forward_reference_picture = VA_INVALID_SURFACE; 315 } 316 picParam->backward_reference_picture = VA_INVALID_SURFACE; 317 break; 318 case MPEG2_PICTURE_TYPE_B: 319 if (mLastReference == NULL || mForwardReference == NULL) { 320 return DECODE_NO_REFERENCE; 321 } else { 322 picParam->forward_reference_picture = mForwardReference->renderBuffer.surface; 323 picParam->backward_reference_picture = mLastReference->renderBuffer.surface; 324 } 325 break; 326 default: 327 // Will never reach here; 328 return DECODE_PARSER_FAIL; 329 } 330 return DECODE_SUCCESS; 331 } 332 333 Decode_Status VideoDecoderMPEG2::startVA(vbp_data_mpeg2 *data) { 334 updateFormatInfo(data); 335 336 VAProfile vaProfile; 337 338 // profile_and_level_indication is 8-bit field 339 // | x | x x x | x x x x| 340 // profile level 341 // profile: 101 - simple 342 // 100 - main 343 // level: 1010 - low 344 // 1000 - main 345 // 0100 - high 346 // 0110 - high 1440 347 if ((data->codec_data->profile_and_level_indication & 0x70) == 0x50) { 348 vaProfile = VAProfileMPEG2Simple; 349 } else { 350 vaProfile = VAProfileMPEG2Main; 351 } 352 353 return VideoDecoderBase::setupVA(MPEG2_SURFACE_NUMBER, vaProfile); 354 } 355 356 Decode_Status VideoDecoderMPEG2::allocateVABufferIDs(int32_t number) { 357 if (mNumBufferIDs > number) { 358 return DECODE_SUCCESS; 359 } 360 if (mBufferIDs) { 361 delete [] mBufferIDs; 362 } 363 mBufferIDs = NULL; 364 mNumBufferIDs = 0; 365 mBufferIDs = new VABufferID [number]; 366 if (mBufferIDs == NULL) { 367 return DECODE_MEMORY_FAIL; 368 } 369 mNumBufferIDs = number; 370 return DECODE_SUCCESS; 371 } 372 373 void VideoDecoderMPEG2::updateFormatInfo(vbp_data_mpeg2 *data) { 374 ITRACE("updateFormatInfo: current size: %d x %d, new size: %d x %d", 375 mVideoFormatInfo.width, mVideoFormatInfo.height, 376 data->codec_data->frame_width, 377 data->codec_data->frame_height); 378 379 mVideoFormatInfo.cropBottom = (data->codec_data->frame_height > mVideoFormatInfo.height) ? 380 (data->codec_data->frame_height - mVideoFormatInfo.height) : 0; 381 mVideoFormatInfo.cropRight = (data->codec_data->frame_width > mVideoFormatInfo.width) ? 382 (data->codec_data->frame_width - mVideoFormatInfo.width) : 0; 383 384 if ((mVideoFormatInfo.width != (uint32_t)data->codec_data->frame_width || 385 mVideoFormatInfo.height != (uint32_t)data->codec_data->frame_height) && 386 (data->codec_data->frame_width > 0) && (data->codec_data->frame_height)) { 387 // update encoded image size 388 mVideoFormatInfo.width = data->codec_data->frame_width; 389 mVideoFormatInfo.height = data->codec_data->frame_height; 390 mSizeChanged = true; 391 ITRACE("Video size is changed."); 392 } 393 394 // video_range has default value of 0. Y ranges from 16 to 235. 395 mVideoFormatInfo.videoRange = data->codec_data->video_range; 396 397 switch (data->codec_data->matrix_coefficients) { 398 case 1: 399 mVideoFormatInfo.colorMatrix = VA_SRC_BT709; 400 break; 401 402 // ITU-R Recommendation BT.470-6 System B, G (MP4), same as 403 // SMPTE 170M/BT601 404 case 5: 405 case 6: 406 mVideoFormatInfo.colorMatrix = VA_SRC_BT601; 407 break; 408 409 default: 410 // unknown color matrix, set to 0 so color space flag will not be set. 411 mVideoFormatInfo.colorMatrix = 0; 412 break; 413 } 414 415 mVideoFormatInfo.aspectX = data->codec_data->par_width; 416 mVideoFormatInfo.aspectY = data->codec_data->par_height; 417 mVideoFormatInfo.bitrate = data->codec_data->bit_rate; 418 mVideoFormatInfo.valid = true; 419 420 setRenderRect(); 421 } 422 423 Decode_Status VideoDecoderMPEG2::checkHardwareCapability() { 424 VAStatus vaStatus; 425 VAConfigAttrib cfgAttribs[2]; 426 cfgAttribs[0].type = VAConfigAttribMaxPictureWidth; 427 cfgAttribs[1].type = VAConfigAttribMaxPictureHeight; 428 vaStatus = vaGetConfigAttributes(mVADisplay, 429 VAProfileMPEG2Main, 430 VAEntrypointVLD, cfgAttribs, 2); 431 CHECK_VA_STATUS("vaGetConfigAttributes"); 432 if (cfgAttribs[0].value * cfgAttribs[1].value < (uint32_t)mVideoFormatInfo.width * (uint32_t)mVideoFormatInfo.height) { 433 ETRACE("hardware supports resolution %d * %d smaller than the clip resolution %d * %d", 434 cfgAttribs[0].value, cfgAttribs[1].value, mVideoFormatInfo.width, mVideoFormatInfo.height); 435 return DECODE_DRIVER_FAIL; 436 } 437 return DECODE_SUCCESS; 438 } 439