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