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