1 /* 2 * Copyright (C) 2011 The Android Open Source Project 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 //#define LOG_NDEBUG 0 18 #define LOG_TAG "SoftMPEG4" 19 #include <utils/Log.h> 20 21 #include "SoftMPEG4.h" 22 23 #include <media/stagefright/foundation/ADebug.h> 24 #include <media/stagefright/foundation/AUtils.h> 25 #include <media/stagefright/MediaDefs.h> 26 #include <media/stagefright/MediaErrors.h> 27 #include <media/IOMX.h> 28 29 #include "mp4dec_api.h" 30 31 namespace android { 32 33 static const CodecProfileLevel kM4VProfileLevels[] = { 34 { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level0 }, 35 { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level0b }, 36 { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level1 }, 37 { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level2 }, 38 { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level3 }, 39 }; 40 41 static const CodecProfileLevel kH263ProfileLevels[] = { 42 { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level10 }, 43 { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level20 }, 44 { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level30 }, 45 { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level45 }, 46 { OMX_VIDEO_H263ProfileISWV2, OMX_VIDEO_H263Level10 }, 47 { OMX_VIDEO_H263ProfileISWV2, OMX_VIDEO_H263Level20 }, 48 { OMX_VIDEO_H263ProfileISWV2, OMX_VIDEO_H263Level30 }, 49 { OMX_VIDEO_H263ProfileISWV2, OMX_VIDEO_H263Level45 }, 50 }; 51 52 SoftMPEG4::SoftMPEG4( 53 const char *name, 54 const char *componentRole, 55 OMX_VIDEO_CODINGTYPE codingType, 56 const CodecProfileLevel *profileLevels, 57 size_t numProfileLevels, 58 const OMX_CALLBACKTYPE *callbacks, 59 OMX_PTR appData, 60 OMX_COMPONENTTYPE **component) 61 : SoftVideoDecoderOMXComponent( 62 name, componentRole, codingType, profileLevels, numProfileLevels, 63 352 /* width */, 288 /* height */, callbacks, appData, component), 64 mMode(codingType == OMX_VIDEO_CodingH263 ? MODE_H263 : MODE_MPEG4), 65 mHandle(new tagvideoDecControls), 66 mInputBufferCount(0), 67 mSignalledError(false), 68 mInitialized(false), 69 mFramesConfigured(false), 70 mNumSamplesOutput(0), 71 mPvTime(0) { 72 initPorts( 73 kNumInputBuffers, 74 352 * 288 * 3 / 2 /* minInputBufferSize */, 75 kNumOutputBuffers, 76 (mMode == MODE_MPEG4) 77 ? MEDIA_MIMETYPE_VIDEO_MPEG4 : MEDIA_MIMETYPE_VIDEO_H263); 78 CHECK_EQ(initDecoder(), (status_t)OK); 79 } 80 81 SoftMPEG4::~SoftMPEG4() { 82 if (mInitialized) { 83 PVCleanUpVideoDecoder(mHandle); 84 } 85 86 delete mHandle; 87 mHandle = NULL; 88 } 89 90 status_t SoftMPEG4::initDecoder() { 91 memset(mHandle, 0, sizeof(tagvideoDecControls)); 92 return OK; 93 } 94 95 void SoftMPEG4::onQueueFilled(OMX_U32 /* portIndex */) { 96 if (mSignalledError || mOutputPortSettingsChange != NONE) { 97 return; 98 } 99 100 List<BufferInfo *> &inQueue = getPortQueue(0); 101 List<BufferInfo *> &outQueue = getPortQueue(1); 102 103 while (!inQueue.empty() && outQueue.size() == kNumOutputBuffers) { 104 BufferInfo *inInfo = *inQueue.begin(); 105 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 106 if (inHeader == NULL) { 107 inQueue.erase(inQueue.begin()); 108 inInfo->mOwnedByUs = false; 109 continue; 110 } 111 112 PortInfo *port = editPortInfo(1); 113 114 OMX_BUFFERHEADERTYPE *outHeader = 115 port->mBuffers.editItemAt(mNumSamplesOutput & 1).mHeader; 116 117 if (inHeader->nFilledLen == 0) { 118 inQueue.erase(inQueue.begin()); 119 inInfo->mOwnedByUs = false; 120 notifyEmptyBufferDone(inHeader); 121 122 ++mInputBufferCount; 123 124 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 125 outHeader->nFilledLen = 0; 126 outHeader->nFlags = OMX_BUFFERFLAG_EOS; 127 128 List<BufferInfo *>::iterator it = outQueue.begin(); 129 while ((*it)->mHeader != outHeader) { 130 ++it; 131 } 132 133 BufferInfo *outInfo = *it; 134 outInfo->mOwnedByUs = false; 135 outQueue.erase(it); 136 outInfo = NULL; 137 138 notifyFillBufferDone(outHeader); 139 outHeader = NULL; 140 } 141 return; 142 } 143 144 uint8_t *bitstream = inHeader->pBuffer + inHeader->nOffset; 145 uint32_t *start_code = (uint32_t *)bitstream; 146 bool volHeader = *start_code == 0xB0010000; 147 if (volHeader) { 148 PVCleanUpVideoDecoder(mHandle); 149 mInitialized = false; 150 } 151 152 if (!mInitialized) { 153 uint8_t *vol_data[1]; 154 int32_t vol_size = 0; 155 156 vol_data[0] = NULL; 157 158 if ((inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) || volHeader) { 159 vol_data[0] = bitstream; 160 vol_size = inHeader->nFilledLen; 161 } 162 163 MP4DecodingMode mode = 164 (mMode == MODE_MPEG4) ? MPEG4_MODE : H263_MODE; 165 166 Bool success = PVInitVideoDecoder( 167 mHandle, vol_data, &vol_size, 1, 168 outputBufferWidth(), outputBufferHeight(), mode); 169 170 if (!success) { 171 ALOGW("PVInitVideoDecoder failed. Unsupported content?"); 172 173 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 174 mSignalledError = true; 175 return; 176 } 177 178 MP4DecodingMode actualMode = PVGetDecBitstreamMode(mHandle); 179 if (mode != actualMode) { 180 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 181 mSignalledError = true; 182 return; 183 } 184 185 PVSetPostProcType((VideoDecControls *) mHandle, 0); 186 187 bool hasFrameData = false; 188 if (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 189 inInfo->mOwnedByUs = false; 190 inQueue.erase(inQueue.begin()); 191 inInfo = NULL; 192 notifyEmptyBufferDone(inHeader); 193 inHeader = NULL; 194 } else if (volHeader) { 195 hasFrameData = true; 196 } 197 198 mInitialized = true; 199 200 if (mode == MPEG4_MODE && handlePortSettingsChange()) { 201 return; 202 } 203 204 if (!hasFrameData) { 205 continue; 206 } 207 } 208 209 if (!mFramesConfigured) { 210 PortInfo *port = editPortInfo(1); 211 OMX_BUFFERHEADERTYPE *outHeader = port->mBuffers.editItemAt(1).mHeader; 212 213 OMX_U32 yFrameSize = sizeof(uint8) * mHandle->size; 214 if ((outHeader->nAllocLen < yFrameSize) || 215 (outHeader->nAllocLen - yFrameSize < yFrameSize / 2)) { 216 ALOGE("Too small output buffer for reference frame: %lu bytes", 217 (unsigned long)outHeader->nAllocLen); 218 android_errorWriteLog(0x534e4554, "30033990"); 219 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 220 mSignalledError = true; 221 return; 222 } 223 PVSetReferenceYUV(mHandle, outHeader->pBuffer); 224 mFramesConfigured = true; 225 } 226 227 uint32_t useExtTimestamp = (inHeader->nOffset == 0); 228 229 // decoder deals in ms (int32_t), OMX in us (int64_t) 230 // so use fake timestamp instead 231 uint32_t timestamp = 0xFFFFFFFF; 232 if (useExtTimestamp) { 233 mPvToOmxTimeMap.add(mPvTime, inHeader->nTimeStamp); 234 timestamp = mPvTime; 235 mPvTime++; 236 } 237 238 int32_t bufferSize = inHeader->nFilledLen; 239 int32_t tmp = bufferSize; 240 241 OMX_U32 frameSize; 242 OMX_U64 yFrameSize = (OMX_U64)mWidth * (OMX_U64)mHeight; 243 if (yFrameSize > ((OMX_U64)UINT32_MAX / 3) * 2) { 244 ALOGE("Frame size too large"); 245 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 246 mSignalledError = true; 247 return; 248 } 249 frameSize = (OMX_U32)(yFrameSize + (yFrameSize / 2)); 250 251 if (outHeader->nAllocLen < frameSize) { 252 android_errorWriteLog(0x534e4554, "27833616"); 253 ALOGE("Insufficient output buffer size"); 254 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 255 mSignalledError = true; 256 return; 257 } 258 259 // Need to check if header contains new info, e.g., width/height, etc. 260 VopHeaderInfo header_info; 261 uint8_t *bitstreamTmp = bitstream; 262 if (PVDecodeVopHeader( 263 mHandle, &bitstreamTmp, ×tamp, &tmp, 264 &header_info, &useExtTimestamp, 265 outHeader->pBuffer) != PV_TRUE) { 266 ALOGE("failed to decode vop header."); 267 268 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 269 mSignalledError = true; 270 return; 271 } 272 if (handlePortSettingsChange()) { 273 return; 274 } 275 276 // The PV decoder is lying to us, sometimes it'll claim to only have 277 // consumed a subset of the buffer when it clearly consumed all of it. 278 // ignore whatever it says... 279 if (PVDecodeVopBody(mHandle, &tmp) != PV_TRUE) { 280 ALOGE("failed to decode video frame."); 281 282 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 283 mSignalledError = true; 284 return; 285 } 286 287 // H263 doesn't have VOL header, the frame size information is in short header, i.e. the 288 // decoder may detect size change after PVDecodeVideoFrame. 289 if (handlePortSettingsChange()) { 290 return; 291 } 292 293 // decoder deals in ms, OMX in us. 294 outHeader->nTimeStamp = mPvToOmxTimeMap.valueFor(timestamp); 295 mPvToOmxTimeMap.removeItem(timestamp); 296 297 inHeader->nOffset += bufferSize; 298 inHeader->nFilledLen = 0; 299 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 300 outHeader->nFlags = OMX_BUFFERFLAG_EOS; 301 } else { 302 outHeader->nFlags = 0; 303 } 304 305 if (inHeader->nFilledLen == 0) { 306 inInfo->mOwnedByUs = false; 307 inQueue.erase(inQueue.begin()); 308 inInfo = NULL; 309 notifyEmptyBufferDone(inHeader); 310 inHeader = NULL; 311 } 312 313 ++mInputBufferCount; 314 315 outHeader->nOffset = 0; 316 outHeader->nFilledLen = frameSize; 317 318 List<BufferInfo *>::iterator it = outQueue.begin(); 319 while ((*it)->mHeader != outHeader) { 320 ++it; 321 } 322 323 BufferInfo *outInfo = *it; 324 outInfo->mOwnedByUs = false; 325 outQueue.erase(it); 326 outInfo = NULL; 327 328 notifyFillBufferDone(outHeader); 329 outHeader = NULL; 330 331 ++mNumSamplesOutput; 332 } 333 } 334 335 bool SoftMPEG4::handlePortSettingsChange() { 336 uint32_t disp_width, disp_height; 337 PVGetVideoDimensions(mHandle, (int32 *)&disp_width, (int32 *)&disp_height); 338 339 uint32_t buf_width, buf_height; 340 PVGetBufferDimensions(mHandle, (int32 *)&buf_width, (int32 *)&buf_height); 341 342 CHECK_LE(disp_width, buf_width); 343 CHECK_LE(disp_height, buf_height); 344 345 ALOGV("disp_width = %d, disp_height = %d, buf_width = %d, buf_height = %d", 346 disp_width, disp_height, buf_width, buf_height); 347 348 CropSettingsMode cropSettingsMode = kCropUnSet; 349 if (disp_width != buf_width || disp_height != buf_height) { 350 cropSettingsMode = kCropSet; 351 352 if (mCropWidth != disp_width || mCropHeight != disp_height) { 353 mCropLeft = 0; 354 mCropTop = 0; 355 mCropWidth = disp_width; 356 mCropHeight = disp_height; 357 cropSettingsMode = kCropChanged; 358 } 359 } 360 361 bool portWillReset = false; 362 const bool fakeStride = true; 363 SoftVideoDecoderOMXComponent::handlePortSettingsChange( 364 &portWillReset, buf_width, buf_height, cropSettingsMode, fakeStride); 365 if (portWillReset) { 366 if (mMode == MODE_H263) { 367 PVCleanUpVideoDecoder(mHandle); 368 369 uint8_t *vol_data[1]; 370 int32_t vol_size = 0; 371 372 vol_data[0] = NULL; 373 if (!PVInitVideoDecoder( 374 mHandle, vol_data, &vol_size, 1, outputBufferWidth(), outputBufferHeight(), 375 H263_MODE)) { 376 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 377 mSignalledError = true; 378 return true; 379 } 380 } 381 382 mFramesConfigured = false; 383 } 384 385 return portWillReset; 386 } 387 388 void SoftMPEG4::onPortFlushCompleted(OMX_U32 portIndex) { 389 if (portIndex == 0 && mInitialized) { 390 CHECK_EQ((int)PVResetVideoDecoder(mHandle), (int)PV_TRUE); 391 } 392 } 393 394 void SoftMPEG4::onReset() { 395 SoftVideoDecoderOMXComponent::onReset(); 396 mPvToOmxTimeMap.clear(); 397 mSignalledError = false; 398 mFramesConfigured = false; 399 if (mInitialized) { 400 PVCleanUpVideoDecoder(mHandle); 401 mInitialized = false; 402 } 403 } 404 405 void SoftMPEG4::updatePortDefinitions(bool updateCrop, bool updateInputSize) { 406 SoftVideoDecoderOMXComponent::updatePortDefinitions(updateCrop, updateInputSize); 407 408 /* We have to align our width and height - this should affect stride! */ 409 OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kOutputPortIndex)->mDef; 410 def->format.video.nStride = align(def->format.video.nStride, 16); 411 def->format.video.nSliceHeight = align(def->format.video.nSliceHeight, 16); 412 def->nBufferSize = (def->format.video.nStride * def->format.video.nSliceHeight * 3) / 2; 413 } 414 415 } // namespace android 416 417 android::SoftOMXComponent *createSoftOMXComponent( 418 const char *name, const OMX_CALLBACKTYPE *callbacks, 419 OMX_PTR appData, OMX_COMPONENTTYPE **component) { 420 using namespace android; 421 if (!strcmp(name, "OMX.google.h263.decoder")) { 422 return new android::SoftMPEG4( 423 name, "video_decoder.h263", OMX_VIDEO_CodingH263, 424 kH263ProfileLevels, ARRAY_SIZE(kH263ProfileLevels), 425 callbacks, appData, component); 426 } else if (!strcmp(name, "OMX.google.mpeg4.decoder")) { 427 return new android::SoftMPEG4( 428 name, "video_decoder.mpeg4", OMX_VIDEO_CodingMPEG4, 429 kM4VProfileLevels, ARRAY_SIZE(kM4VProfileLevels), 430 callbacks, appData, component); 431 } else { 432 CHECK(!"Unknown component"); 433 } 434 return NULL; 435 } 436 437