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