blob: 761dfa4260bf90bf699ee567df98b2ec844147fb [file] [log] [blame]
Andreas Huberf9334412010-12-15 15:17:42 -08001/*
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>
Andreas Huber5bc087c2010-12-23 10:27:40 -080028#include <media/stagefright/foundation/AMessage.h>
Andreas Huberf9334412010-12-15 15:17:42 -080029#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> &notify, const sp<Surface> &surface)
39 : mNotify(notify),
40 mSurface(surface) {
41}
42
43NuPlayer::Decoder::~Decoder() {
44}
45
Andreas Huber5bc087c2010-12-23 10:27:40 -080046void NuPlayer::Decoder::configure(const sp<MetaData> &meta) {
Andreas Huberf9334412010-12-15 15:17:42 -080047 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
Andreas Huber5bc087c2010-12-23 10:27:40 -0800127 int32_t maxInputSize;
128 if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) {
129 msg->setInt32("max-input-size", maxInputSize);
130 }
131
132 mCSDIndex = 0;
133
Andreas Huberf9334412010-12-15 15:17:42 -0800134 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
Andreas Huberf9334412010-12-15 15:17:42 -0800239 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
Andreas Huber3831a062010-12-21 10:22:33 -0800286void NuPlayer::Decoder::initiateShutdown() {
287 if (mCodec != NULL) {
288 mCodec->initiateShutdown();
289 } else {
290 CHECK(mWrapper != NULL);
291 mWrapper->initiateShutdown();
292 }
293}
294
Andreas Huberf9334412010-12-15 15:17:42 -0800295} // namespace android
296