NuPlayerDecoder.cpp revision 00f4951088805442e86ff9c2a20ddad79fc2410a
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#include <surfaceflinger/Surface.h> 33#include <gui/ISurfaceTexture.h> 34 35namespace android { 36 37NuPlayer::Decoder::Decoder( 38 const sp<AMessage> ¬ify, 39 const sp<NativeWindowWrapper> &nativeWindow) 40 : mNotify(notify), 41 mNativeWindow(nativeWindow) { 42} 43 44NuPlayer::Decoder::~Decoder() { 45} 46 47void NuPlayer::Decoder::configure(const sp<MetaData> &meta) { 48 CHECK(mCodec == 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 (mNativeWindow != NULL) { 59 format->setObject("native-window", mNativeWindow); 60 } 61 62 mCodec = new ACodec; 63 looper()->registerHandler(mCodec); 64 65 mCodec->setNotificationMessage(notifyMsg); 66 mCodec->initiateSetup(format); 67} 68 69void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) { 70 switch (msg->what()) { 71 case kWhatCodecNotify: 72 { 73 int32_t what; 74 CHECK(msg->findInt32("what", &what)); 75 76 if (what == ACodec::kWhatFillThisBuffer) { 77 onFillThisBuffer(msg); 78 } else { 79 sp<AMessage> notify = mNotify->dup(); 80 notify->setMessage("codec-request", msg); 81 notify->post(); 82 } 83 break; 84 } 85 86 default: 87 TRESPASS(); 88 break; 89 } 90} 91 92sp<AMessage> NuPlayer::Decoder::makeFormat(const sp<MetaData> &meta) { 93 CHECK(mCSD.isEmpty()); 94 95 const char *mime; 96 CHECK(meta->findCString(kKeyMIMEType, &mime)); 97 98 sp<AMessage> msg = new AMessage; 99 msg->setString("mime", mime); 100 101 if (!strncasecmp("video/", mime, 6)) { 102 int32_t width, height; 103 CHECK(meta->findInt32(kKeyWidth, &width)); 104 CHECK(meta->findInt32(kKeyHeight, &height)); 105 106 msg->setInt32("width", width); 107 msg->setInt32("height", height); 108 } else { 109 CHECK(!strncasecmp("audio/", mime, 6)); 110 111 int32_t numChannels, sampleRate; 112 CHECK(meta->findInt32(kKeyChannelCount, &numChannels)); 113 CHECK(meta->findInt32(kKeySampleRate, &sampleRate)); 114 115 msg->setInt32("channel-count", numChannels); 116 msg->setInt32("sample-rate", sampleRate); 117 } 118 119 int32_t maxInputSize; 120 if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) { 121 msg->setInt32("max-input-size", maxInputSize); 122 } 123 124 mCSDIndex = 0; 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 ESDS esds((const char *)data, size); 208 CHECK_EQ(esds.InitCheck(), (status_t)OK); 209 210 const void *codec_specific_data; 211 size_t codec_specific_data_size; 212 esds.getCodecSpecificInfo( 213 &codec_specific_data, &codec_specific_data_size); 214 215 sp<ABuffer> buffer = new ABuffer(codec_specific_data_size); 216 217 memcpy(buffer->data(), codec_specific_data, 218 codec_specific_data_size); 219 220 buffer->meta()->setInt32("csd", true); 221 mCSD.push(buffer); 222 } 223 224 return msg; 225} 226 227void NuPlayer::Decoder::onFillThisBuffer(const sp<AMessage> &msg) { 228 sp<AMessage> reply; 229 CHECK(msg->findMessage("reply", &reply)); 230 231#if 0 232 sp<RefBase> obj; 233 CHECK(msg->findObject("buffer", &obj)); 234 sp<ABuffer> outBuffer = static_cast<ABuffer *>(obj.get()); 235#else 236 sp<ABuffer> outBuffer; 237#endif 238 239 if (mCSDIndex < mCSD.size()) { 240 outBuffer = mCSD.editItemAt(mCSDIndex++); 241 outBuffer->meta()->setInt64("timeUs", 0); 242 243 reply->setObject("buffer", outBuffer); 244 reply->post(); 245 return; 246 } 247 248 sp<AMessage> notify = mNotify->dup(); 249 notify->setMessage("codec-request", msg); 250 notify->post(); 251} 252 253void NuPlayer::Decoder::signalFlush() { 254 if (mCodec != NULL) { 255 mCodec->signalFlush(); 256 } 257} 258 259void NuPlayer::Decoder::signalResume() { 260 if (mCodec != NULL) { 261 mCodec->signalResume(); 262 } 263} 264 265void NuPlayer::Decoder::initiateShutdown() { 266 if (mCodec != NULL) { 267 mCodec->initiateShutdown(); 268 } 269} 270 271} // namespace android 272 273