NuPlayerDecoder.cpp revision ed3e3e046840d5bf1ca84a8c0cc097425e89d6d6
1/* 2 * Copyright (C) 2010 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 "NuPlayerDecoder" 19#include <utils/Log.h> 20 21#include "NuPlayerDecoder.h" 22 23#include "ESDS.h" 24 25#include <media/stagefright/foundation/ABuffer.h> 26#include <media/stagefright/foundation/ADebug.h> 27#include <media/stagefright/foundation/AMessage.h> 28#include <media/stagefright/ACodec.h> 29#include <media/stagefright/MediaDefs.h> 30#include <media/stagefright/MetaData.h> 31#include <media/stagefright/Utils.h> 32 33namespace android { 34 35NuPlayer::Decoder::Decoder( 36 const sp<AMessage> ¬ify, 37 const sp<NativeWindowWrapper> &nativeWindow) 38 : mNotify(notify), 39 mNativeWindow(nativeWindow) { 40} 41 42NuPlayer::Decoder::~Decoder() { 43} 44 45void NuPlayer::Decoder::configure(const sp<MetaData> &meta) { 46 CHECK(mCodec == NULL); 47 48 const char *mime; 49 CHECK(meta->findCString(kKeyMIMEType, &mime)); 50 51 sp<AMessage> notifyMsg = 52 new AMessage(kWhatCodecNotify, id()); 53 54 sp<AMessage> format = makeFormat(meta); 55 56 if (mNativeWindow != NULL) { 57 format->setObject("native-window", mNativeWindow); 58 } 59 60 // Current video decoders do not return from OMX_FillThisBuffer 61 // quickly, violating the OpenMAX specs, until that is remedied 62 // we need to invest in an extra looper to free the main event 63 // queue. 64 bool needDedicatedLooper = !strncasecmp(mime, "video/", 6); 65 66 mCodec = new ACodec; 67 68 if (needDedicatedLooper && mCodecLooper == NULL) { 69 mCodecLooper = new ALooper; 70 mCodecLooper->setName("NuPlayerDecoder"); 71 mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO); 72 } 73 74 (needDedicatedLooper ? mCodecLooper : looper())->registerHandler(mCodec); 75 76 mCodec->setNotificationMessage(notifyMsg); 77 mCodec->initiateSetup(format); 78} 79 80void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) { 81 switch (msg->what()) { 82 case kWhatCodecNotify: 83 { 84 int32_t what; 85 CHECK(msg->findInt32("what", &what)); 86 87 if (what == ACodec::kWhatFillThisBuffer) { 88 onFillThisBuffer(msg); 89 } else { 90 sp<AMessage> notify = mNotify->dup(); 91 notify->setMessage("codec-request", msg); 92 notify->post(); 93 } 94 break; 95 } 96 97 default: 98 TRESPASS(); 99 break; 100 } 101} 102 103sp<AMessage> NuPlayer::Decoder::makeFormat(const sp<MetaData> &meta) { 104 CHECK(mCSD.isEmpty()); 105 106 const char *mime; 107 CHECK(meta->findCString(kKeyMIMEType, &mime)); 108 109 sp<AMessage> msg = new AMessage; 110 msg->setString("mime", mime); 111 112 if (!strncasecmp("video/", mime, 6)) { 113 int32_t width, height; 114 CHECK(meta->findInt32(kKeyWidth, &width)); 115 CHECK(meta->findInt32(kKeyHeight, &height)); 116 117 msg->setInt32("width", width); 118 msg->setInt32("height", height); 119 } else { 120 CHECK(!strncasecmp("audio/", mime, 6)); 121 122 int32_t numChannels, sampleRate; 123 CHECK(meta->findInt32(kKeyChannelCount, &numChannels)); 124 CHECK(meta->findInt32(kKeySampleRate, &sampleRate)); 125 126 msg->setInt32("channel-count", numChannels); 127 msg->setInt32("sample-rate", sampleRate); 128 129 int32_t isADTS; 130 if (meta->findInt32(kKeyIsADTS, &isADTS) && isADTS != 0) { 131 msg->setInt32("is-adts", true); 132 } 133 } 134 135 int32_t maxInputSize; 136 if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) { 137 msg->setInt32("max-input-size", maxInputSize); 138 } 139 140 mCSDIndex = 0; 141 142 uint32_t type; 143 const void *data; 144 size_t size; 145 if (meta->findData(kKeyAVCC, &type, &data, &size)) { 146 // Parse the AVCDecoderConfigurationRecord 147 148 const uint8_t *ptr = (const uint8_t *)data; 149 150 CHECK(size >= 7); 151 CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1 152 uint8_t profile = ptr[1]; 153 uint8_t level = ptr[3]; 154 155 // There is decodable content out there that fails the following 156 // assertion, let's be lenient for now... 157 // CHECK((ptr[4] >> 2) == 0x3f); // reserved 158 159 size_t lengthSize = 1 + (ptr[4] & 3); 160 161 // commented out check below as H264_QVGA_500_NO_AUDIO.3gp 162 // violates it... 163 // CHECK((ptr[5] >> 5) == 7); // reserved 164 165 size_t numSeqParameterSets = ptr[5] & 31; 166 167 ptr += 6; 168 size -= 6; 169 170 sp<ABuffer> buffer = new ABuffer(1024); 171 buffer->setRange(0, 0); 172 173 for (size_t i = 0; i < numSeqParameterSets; ++i) { 174 CHECK(size >= 2); 175 size_t length = U16_AT(ptr); 176 177 ptr += 2; 178 size -= 2; 179 180 CHECK(size >= length); 181 182 memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4); 183 memcpy(buffer->data() + buffer->size() + 4, ptr, length); 184 buffer->setRange(0, buffer->size() + 4 + length); 185 186 ptr += length; 187 size -= length; 188 } 189 190 buffer->meta()->setInt32("csd", true); 191 mCSD.push(buffer); 192 193 buffer = new ABuffer(1024); 194 buffer->setRange(0, 0); 195 196 CHECK(size >= 1); 197 size_t numPictureParameterSets = *ptr; 198 ++ptr; 199 --size; 200 201 for (size_t i = 0; i < numPictureParameterSets; ++i) { 202 CHECK(size >= 2); 203 size_t length = U16_AT(ptr); 204 205 ptr += 2; 206 size -= 2; 207 208 CHECK(size >= length); 209 210 memcpy(buffer->data() + buffer->size(), "\x00\x00\x00\x01", 4); 211 memcpy(buffer->data() + buffer->size() + 4, ptr, length); 212 buffer->setRange(0, buffer->size() + 4 + length); 213 214 ptr += length; 215 size -= length; 216 } 217 218 buffer->meta()->setInt32("csd", true); 219 mCSD.push(buffer); 220 } else if (meta->findData(kKeyESDS, &type, &data, &size)) { 221 ESDS esds((const char *)data, size); 222 CHECK_EQ(esds.InitCheck(), (status_t)OK); 223 224 const void *codec_specific_data; 225 size_t codec_specific_data_size; 226 esds.getCodecSpecificInfo( 227 &codec_specific_data, &codec_specific_data_size); 228 229 sp<ABuffer> buffer = new ABuffer(codec_specific_data_size); 230 231 memcpy(buffer->data(), codec_specific_data, 232 codec_specific_data_size); 233 234 buffer->meta()->setInt32("csd", true); 235 mCSD.push(buffer); 236 } else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) { 237 sp<ABuffer> buffer = new ABuffer(size); 238 memcpy(buffer->data(), data, size); 239 240 buffer->meta()->setInt32("csd", true); 241 mCSD.push(buffer); 242 243 CHECK(meta->findData(kKeyVorbisBooks, &type, &data, &size)); 244 245 buffer = new ABuffer(size); 246 memcpy(buffer->data(), data, size); 247 248 buffer->meta()->setInt32("csd", true); 249 mCSD.push(buffer); 250 } 251 252 return msg; 253} 254 255void NuPlayer::Decoder::onFillThisBuffer(const sp<AMessage> &msg) { 256 sp<AMessage> reply; 257 CHECK(msg->findMessage("reply", &reply)); 258 259#if 0 260 sp<ABuffer> outBuffer; 261 CHECK(msg->findBuffer("buffer", &outBuffer)); 262#else 263 sp<ABuffer> outBuffer; 264#endif 265 266 if (mCSDIndex < mCSD.size()) { 267 outBuffer = mCSD.editItemAt(mCSDIndex++); 268 outBuffer->meta()->setInt64("timeUs", 0); 269 270 reply->setBuffer("buffer", outBuffer); 271 reply->post(); 272 return; 273 } 274 275 sp<AMessage> notify = mNotify->dup(); 276 notify->setMessage("codec-request", msg); 277 notify->post(); 278} 279 280void NuPlayer::Decoder::signalFlush() { 281 if (mCodec != NULL) { 282 mCodec->signalFlush(); 283 } 284} 285 286void NuPlayer::Decoder::signalResume() { 287 if (mCodec != NULL) { 288 mCodec->signalResume(); 289 } 290} 291 292void NuPlayer::Decoder::initiateShutdown() { 293 if (mCodec != NULL) { 294 mCodec->initiateShutdown(); 295 } 296} 297 298} // namespace android 299 300