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