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