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