blob: 490129fe840260453f97abfd7b310b3e234059fc [file] [log] [blame]
Andreas Huber4a0ec3f2009-12-10 09:44:29 -08001/*
2 * Copyright (C) 2009 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
Andreas Huberb5ae1c82009-12-14 10:53:00 -080017//#define LOG_NDEBUG 0
18#define LOG_TAG "AVCDecoder"
19#include <utils/Log.h>
20
Andreas Huber4a0ec3f2009-12-10 09:44:29 -080021#include "AVCDecoder.h"
22
23#include "avcdec_api.h"
24#include "avcdec_int.h"
25
26#include <OMX_Component.h>
27
28#include <media/stagefright/MediaBufferGroup.h>
29#include <media/stagefright/MediaDebug.h>
30#include <media/stagefright/MediaDefs.h>
31#include <media/stagefright/MediaErrors.h>
32#include <media/stagefright/MetaData.h>
33#include <media/stagefright/Utils.h>
Andreas Huberb72c7e32010-10-01 10:51:41 -070034#include <media/stagefright/foundation/hexdump.h>
Andreas Huber4a0ec3f2009-12-10 09:44:29 -080035
36namespace android {
37
Andreas Huber94020382010-05-12 16:30:12 -070038static const char kStartCode[4] = { 0x00, 0x00, 0x00, 0x01 };
39
Andreas Huber4a0ec3f2009-12-10 09:44:29 -080040static int32_t Malloc(void *userData, int32_t size, int32_t attrs) {
41 return reinterpret_cast<int32_t>(malloc(size));
42}
43
44static void Free(void *userData, int32_t ptr) {
45 free(reinterpret_cast<void *>(ptr));
46}
47
48AVCDecoder::AVCDecoder(const sp<MediaSource> &source)
49 : mSource(source),
50 mStarted(false),
51 mHandle(new tagAVCHandle),
52 mInputBuffer(NULL),
53 mAnchorTimeUs(0),
Andreas Huberb5ae1c82009-12-14 10:53:00 -080054 mNumSamplesOutput(0),
Andreas Huber6624c9f2010-07-20 15:04:28 -070055 mPendingSeekTimeUs(-1),
56 mPendingSeekMode(MediaSource::ReadOptions::SEEK_CLOSEST_SYNC),
Andreas Huber15644552010-08-04 13:04:46 -070057 mTargetTimeUs(-1),
58 mSPSSeen(false),
59 mPPSSeen(false) {
Andreas Huber4a0ec3f2009-12-10 09:44:29 -080060 memset(mHandle, 0, sizeof(tagAVCHandle));
61 mHandle->AVCObject = NULL;
62 mHandle->userData = this;
63 mHandle->CBAVC_DPBAlloc = ActivateSPSWrapper;
64 mHandle->CBAVC_FrameBind = BindFrameWrapper;
65 mHandle->CBAVC_FrameUnbind = UnbindFrame;
66 mHandle->CBAVC_Malloc = Malloc;
67 mHandle->CBAVC_Free = Free;
68
69 mFormat = new MetaData;
70 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
71 int32_t width, height;
72 CHECK(mSource->getFormat()->findInt32(kKeyWidth, &width));
73 CHECK(mSource->getFormat()->findInt32(kKeyHeight, &height));
74 mFormat->setInt32(kKeyWidth, width);
75 mFormat->setInt32(kKeyHeight, height);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -080076 mFormat->setRect(kKeyCropRect, 0, 0, width - 1, height - 1);
Andreas Huber4a0ec3f2009-12-10 09:44:29 -080077 mFormat->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar);
78 mFormat->setCString(kKeyDecoderComponent, "AVCDecoder");
Andreas Huber85adf5e2009-12-11 11:27:02 -080079
80 int64_t durationUs;
81 if (mSource->getFormat()->findInt64(kKeyDuration, &durationUs)) {
82 mFormat->setInt64(kKeyDuration, durationUs);
83 }
Andreas Huber4a0ec3f2009-12-10 09:44:29 -080084}
85
86AVCDecoder::~AVCDecoder() {
87 if (mStarted) {
88 stop();
89 }
90
Andreas Huber98b48de2010-01-29 10:10:22 -080091 PVAVCCleanUpDecoder(mHandle);
92
Andreas Huber4a0ec3f2009-12-10 09:44:29 -080093 delete mHandle;
94 mHandle = NULL;
95}
96
97status_t AVCDecoder::start(MetaData *) {
98 CHECK(!mStarted);
99
100 uint32_t type;
101 const void *data;
102 size_t size;
Andreas Huberdd0359f2010-01-05 11:13:08 -0800103 sp<MetaData> meta = mSource->getFormat();
104 if (meta->findData(kKeyAVCC, &type, &data, &size)) {
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800105 // Parse the AVCDecoderConfigurationRecord
106
107 const uint8_t *ptr = (const uint8_t *)data;
108
109 CHECK(size >= 7);
110 CHECK_EQ(ptr[0], 1); // configurationVersion == 1
111 uint8_t profile = ptr[1];
112 uint8_t level = ptr[3];
113
114 // There is decodable content out there that fails the following
115 // assertion, let's be lenient for now...
116 // CHECK((ptr[4] >> 2) == 0x3f); // reserved
117
118 size_t lengthSize = 1 + (ptr[4] & 3);
119
120 // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
121 // violates it...
122 // CHECK((ptr[5] >> 5) == 7); // reserved
123
124 size_t numSeqParameterSets = ptr[5] & 31;
125
126 ptr += 6;
127 size -= 6;
128
129 for (size_t i = 0; i < numSeqParameterSets; ++i) {
130 CHECK(size >= 2);
131 size_t length = U16_AT(ptr);
132
133 ptr += 2;
134 size -= 2;
135
136 CHECK(size >= length);
137
138 addCodecSpecificData(ptr, length);
139
140 ptr += length;
141 size -= length;
142 }
143
144 CHECK(size >= 1);
145 size_t numPictureParameterSets = *ptr;
146 ++ptr;
147 --size;
148
149 for (size_t i = 0; i < numPictureParameterSets; ++i) {
150 CHECK(size >= 2);
151 size_t length = U16_AT(ptr);
152
153 ptr += 2;
154 size -= 2;
155
156 CHECK(size >= length);
157
158 addCodecSpecificData(ptr, length);
159
160 ptr += length;
161 size -= length;
162 }
163 }
164
Andreas Huber94020382010-05-12 16:30:12 -0700165 mSource->start();
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800166
167 mAnchorTimeUs = 0;
168 mNumSamplesOutput = 0;
Andreas Huberb5ae1c82009-12-14 10:53:00 -0800169 mPendingSeekTimeUs = -1;
Andreas Huber6624c9f2010-07-20 15:04:28 -0700170 mPendingSeekMode = ReadOptions::SEEK_CLOSEST_SYNC;
171 mTargetTimeUs = -1;
Andreas Huber15644552010-08-04 13:04:46 -0700172 mSPSSeen = false;
173 mPPSSeen = false;
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800174 mStarted = true;
175
176 return OK;
177}
178
179void AVCDecoder::addCodecSpecificData(const uint8_t *data, size_t size) {
Andreas Huber94020382010-05-12 16:30:12 -0700180 MediaBuffer *buffer = new MediaBuffer(size + 4);
181 memcpy(buffer->data(), kStartCode, 4);
182 memcpy((uint8_t *)buffer->data() + 4, data, size);
183 buffer->set_range(0, size + 4);
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800184
185 mCodecSpecificData.push(buffer);
186}
187
188status_t AVCDecoder::stop() {
189 CHECK(mStarted);
190
191 for (size_t i = 0; i < mCodecSpecificData.size(); ++i) {
192 (*mCodecSpecificData.editItemAt(i)).release();
193 }
194 mCodecSpecificData.clear();
195
196 if (mInputBuffer) {
197 mInputBuffer->release();
198 mInputBuffer = NULL;
199 }
200
201 mSource->stop();
202
203 releaseFrames();
204
205 mStarted = false;
206
207 return OK;
208}
209
210sp<MetaData> AVCDecoder::getFormat() {
211 return mFormat;
212}
213
Andreas Huber94020382010-05-12 16:30:12 -0700214static void findNALFragment(
215 const MediaBuffer *buffer, const uint8_t **fragPtr, size_t *fragSize) {
216 const uint8_t *data =
217 (const uint8_t *)buffer->data() + buffer->range_offset();
218
219 size_t size = buffer->range_length();
220
221 CHECK(size >= 4);
222 CHECK(!memcmp(kStartCode, data, 4));
223
224 size_t offset = 4;
225 while (offset + 3 < size && memcmp(kStartCode, &data[offset], 4)) {
226 ++offset;
227 }
228
229 *fragPtr = &data[4];
230 if (offset + 3 >= size) {
231 *fragSize = size - 4;
232 } else {
233 *fragSize = offset - 4;
234 }
235}
236
Andreas Huber55f8aee2010-09-22 11:47:00 -0700237MediaBuffer *AVCDecoder::drainOutputBuffer() {
238 int32_t index;
239 int32_t Release;
240 AVCFrameIO Output;
241 Output.YCbCr[0] = Output.YCbCr[1] = Output.YCbCr[2] = NULL;
242 AVCDec_Status status = PVAVCDecGetOutput(mHandle, &index, &Release, &Output);
243
244 if (status != AVCDEC_SUCCESS) {
245 LOGV("PVAVCDecGetOutput returned error %d", status);
246 return NULL;
247 }
248
249 CHECK(index >= 0);
250 CHECK(index < (int32_t)mFrames.size());
251
252 MediaBuffer *mbuf = mFrames.editItemAt(index);
253
254 bool skipFrame = false;
255
256 if (mTargetTimeUs >= 0) {
257 int64_t timeUs;
258 CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
259 CHECK(timeUs <= mTargetTimeUs);
260
261 if (timeUs < mTargetTimeUs) {
262 // We're still waiting for the frame with the matching
263 // timestamp and we won't return the current one.
264 skipFrame = true;
265
266 LOGV("skipping frame at %lld us", timeUs);
267 } else {
268 LOGV("found target frame at %lld us", timeUs);
269
270 mTargetTimeUs = -1;
271 }
272 }
273
274 if (!skipFrame) {
275 mbuf->set_range(0, mbuf->size());
276 mbuf->add_ref();
277
278 return mbuf;
279 }
280
281 return new MediaBuffer(0);
282}
283
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800284status_t AVCDecoder::read(
285 MediaBuffer **out, const ReadOptions *options) {
286 *out = NULL;
287
Andreas Huberb5ae1c82009-12-14 10:53:00 -0800288 int64_t seekTimeUs;
Andreas Huber6624c9f2010-07-20 15:04:28 -0700289 ReadOptions::SeekMode mode;
290 if (options && options->getSeekTo(&seekTimeUs, &mode)) {
Andreas Huberb5ae1c82009-12-14 10:53:00 -0800291 LOGV("seek requested to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6);
292
293 CHECK(seekTimeUs >= 0);
294 mPendingSeekTimeUs = seekTimeUs;
Andreas Huber6624c9f2010-07-20 15:04:28 -0700295 mPendingSeekMode = mode;
Andreas Huberb5ae1c82009-12-14 10:53:00 -0800296
297 if (mInputBuffer) {
298 mInputBuffer->release();
299 mInputBuffer = NULL;
300 }
301
302 PVAVCDecReset(mHandle);
303 }
304
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800305 if (mInputBuffer == NULL) {
306 LOGV("fetching new input buffer.");
307
Andreas Huber6624c9f2010-07-20 15:04:28 -0700308 bool seeking = false;
309
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800310 if (!mCodecSpecificData.isEmpty()) {
311 mInputBuffer = mCodecSpecificData.editItemAt(0);
312 mCodecSpecificData.removeAt(0);
313 } else {
314 for (;;) {
Andreas Huberb5ae1c82009-12-14 10:53:00 -0800315 if (mPendingSeekTimeUs >= 0) {
316 LOGV("reading data from timestamp %lld (%.2f secs)",
317 mPendingSeekTimeUs, mPendingSeekTimeUs / 1E6);
318 }
319
320 ReadOptions seekOptions;
321 if (mPendingSeekTimeUs >= 0) {
Andreas Huber6624c9f2010-07-20 15:04:28 -0700322 seeking = true;
323
324 seekOptions.setSeekTo(mPendingSeekTimeUs, mPendingSeekMode);
Andreas Huberb5ae1c82009-12-14 10:53:00 -0800325 mPendingSeekTimeUs = -1;
326 }
327 status_t err = mSource->read(&mInputBuffer, &seekOptions);
328 seekOptions.clearSeekTo();
329
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800330 if (err != OK) {
Andreas Huber55f8aee2010-09-22 11:47:00 -0700331 *out = drainOutputBuffer();
332 return (*out == NULL) ? err : (status_t)OK;
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800333 }
334
335 if (mInputBuffer->range_length() > 0) {
336 break;
337 }
338
339 mInputBuffer->release();
340 mInputBuffer = NULL;
341 }
342 }
Andreas Huber6624c9f2010-07-20 15:04:28 -0700343
344 if (seeking) {
345 int64_t targetTimeUs;
346 if (mInputBuffer->meta_data()->findInt64(kKeyTargetTime, &targetTimeUs)
347 && targetTimeUs >= 0) {
348 mTargetTimeUs = targetTimeUs;
349 } else {
350 mTargetTimeUs = -1;
351 }
352 }
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800353 }
354
Andreas Huber94020382010-05-12 16:30:12 -0700355 const uint8_t *fragPtr;
356 size_t fragSize;
357 findNALFragment(mInputBuffer, &fragPtr, &fragSize);
358
359 bool releaseFragment = true;
360 status_t err = UNKNOWN_ERROR;
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800361
362 int nalType;
363 int nalRefIdc;
364 AVCDec_Status res =
365 PVAVCDecGetNALType(
Andreas Huber94020382010-05-12 16:30:12 -0700366 const_cast<uint8_t *>(fragPtr), fragSize,
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800367 &nalType, &nalRefIdc);
368
369 if (res != AVCDEC_SUCCESS) {
Andreas Huber45922df2010-09-16 10:25:34 -0700370 LOGV("cannot determine nal type");
Andreas Huber15644552010-08-04 13:04:46 -0700371 } else if (nalType == AVC_NALTYPE_SPS || nalType == AVC_NALTYPE_PPS
372 || (mSPSSeen && mPPSSeen)) {
373 switch (nalType) {
374 case AVC_NALTYPE_SPS:
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800375 {
Andreas Huber15644552010-08-04 13:04:46 -0700376 mSPSSeen = true;
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800377
Andreas Huber15644552010-08-04 13:04:46 -0700378 res = PVAVCDecSeqParamSet(
379 mHandle, const_cast<uint8_t *>(fragPtr),
380 fragSize);
381
382 if (res != AVCDEC_SUCCESS) {
Andreas Huber45922df2010-09-16 10:25:34 -0700383 LOGV("PVAVCDecSeqParamSet returned error %d", res);
Andreas Huber15644552010-08-04 13:04:46 -0700384 break;
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800385 }
Andreas Huber15644552010-08-04 13:04:46 -0700386
387 AVCDecObject *pDecVid = (AVCDecObject *)mHandle->AVCObject;
388
389 int32_t width =
390 (pDecVid->seqParams[0]->pic_width_in_mbs_minus1 + 1) * 16;
391
392 int32_t height =
393 (pDecVid->seqParams[0]->pic_height_in_map_units_minus1 + 1) * 16;
394
395 int32_t crop_left, crop_right, crop_top, crop_bottom;
396 if (pDecVid->seqParams[0]->frame_cropping_flag)
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800397 {
Andreas Huber15644552010-08-04 13:04:46 -0700398 crop_left = 2 * pDecVid->seqParams[0]->frame_crop_left_offset;
399 crop_right =
400 width - (2 * pDecVid->seqParams[0]->frame_crop_right_offset + 1);
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800401
Andreas Huber15644552010-08-04 13:04:46 -0700402 if (pDecVid->seqParams[0]->frame_mbs_only_flag)
403 {
404 crop_top = 2 * pDecVid->seqParams[0]->frame_crop_top_offset;
405 crop_bottom =
406 height -
407 (2 * pDecVid->seqParams[0]->frame_crop_bottom_offset + 1);
Andreas Huber6624c9f2010-07-20 15:04:28 -0700408 }
Andreas Huber15644552010-08-04 13:04:46 -0700409 else
410 {
411 crop_top = 4 * pDecVid->seqParams[0]->frame_crop_top_offset;
412 crop_bottom =
413 height -
414 (4 * pDecVid->seqParams[0]->frame_crop_bottom_offset + 1);
415 }
416 } else {
417 crop_bottom = height - 1;
418 crop_right = width - 1;
419 crop_top = crop_left = 0;
Andreas Huber6624c9f2010-07-20 15:04:28 -0700420 }
421
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800422 int32_t prevCropLeft, prevCropTop;
423 int32_t prevCropRight, prevCropBottom;
424 if (!mFormat->findRect(
425 kKeyCropRect,
426 &prevCropLeft, &prevCropTop,
427 &prevCropRight, &prevCropBottom)) {
428 prevCropLeft = prevCropTop = 0;
429 prevCropRight = width - 1;
430 prevCropBottom = height - 1;
431 }
Andreas Huber15644552010-08-04 13:04:46 -0700432
433 int32_t oldWidth, oldHeight;
434 CHECK(mFormat->findInt32(kKeyWidth, &oldWidth));
435 CHECK(mFormat->findInt32(kKeyHeight, &oldHeight));
436
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800437 if (oldWidth != width || oldHeight != height
438 || prevCropLeft != crop_left
439 || prevCropTop != crop_top
440 || prevCropRight != crop_right
441 || prevCropBottom != crop_bottom) {
442 mFormat->setRect(
443 kKeyCropRect,
444 crop_left, crop_top, crop_right, crop_bottom);
445
446 mFormat->setInt32(kKeyWidth, width);
447 mFormat->setInt32(kKeyHeight, height);
Andreas Huber15644552010-08-04 13:04:46 -0700448
449 err = INFO_FORMAT_CHANGED;
Andreas Huber6624c9f2010-07-20 15:04:28 -0700450 } else {
451 *out = new MediaBuffer(0);
Andreas Huber15644552010-08-04 13:04:46 -0700452 err = OK;
Andreas Huber6624c9f2010-07-20 15:04:28 -0700453 }
Andreas Huber94020382010-05-12 16:30:12 -0700454 break;
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800455 }
456
Andreas Huber15644552010-08-04 13:04:46 -0700457 case AVC_NALTYPE_PPS:
458 {
459 mPPSSeen = true;
460
461 res = PVAVCDecPicParamSet(
462 mHandle, const_cast<uint8_t *>(fragPtr),
463 fragSize);
464
465 if (res != AVCDEC_SUCCESS) {
Andreas Huber45922df2010-09-16 10:25:34 -0700466 LOGV("PVAVCDecPicParamSet returned error %d", res);
Andreas Huber15644552010-08-04 13:04:46 -0700467 break;
468 }
469
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800470 *out = new MediaBuffer(0);
471
Andreas Huber94020382010-05-12 16:30:12 -0700472 err = OK;
Andreas Huber94020382010-05-12 16:30:12 -0700473 break;
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800474 }
475
Andreas Huber15644552010-08-04 13:04:46 -0700476 case AVC_NALTYPE_SLICE:
477 case AVC_NALTYPE_IDR:
478 {
479 res = PVAVCDecodeSlice(
480 mHandle, const_cast<uint8_t *>(fragPtr),
481 fragSize);
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800482
Andreas Huber15644552010-08-04 13:04:46 -0700483 if (res == AVCDEC_PICTURE_OUTPUT_READY) {
Andreas Huber55f8aee2010-09-22 11:47:00 -0700484 MediaBuffer *mbuf = drainOutputBuffer();
485 if (mbuf == NULL) {
Andreas Huber45922df2010-09-16 10:25:34 -0700486 break;
487 }
Andreas Huber15644552010-08-04 13:04:46 -0700488
Andreas Huber55f8aee2010-09-22 11:47:00 -0700489 *out = mbuf;
Andreas Huber15644552010-08-04 13:04:46 -0700490
491 // Do _not_ release input buffer yet.
492
493 releaseFragment = false;
494 err = OK;
495 break;
496 }
497
498 if (res == AVCDEC_PICTURE_READY || res == AVCDEC_SUCCESS) {
499 *out = new MediaBuffer(0);
500
501 err = OK;
502 } else {
Andreas Huber45922df2010-09-16 10:25:34 -0700503 LOGV("PVAVCDecodeSlice returned error %d", res);
Andreas Huber15644552010-08-04 13:04:46 -0700504 }
505 break;
506 }
507
508 case AVC_NALTYPE_SEI:
509 {
510 res = PVAVCDecSEI(
511 mHandle, const_cast<uint8_t *>(fragPtr),
512 fragSize);
513
514 if (res != AVCDEC_SUCCESS) {
515 break;
516 }
517
518 *out = new MediaBuffer(0);
519
520 err = OK;
521 break;
522 }
523
524 case AVC_NALTYPE_AUD:
525 case AVC_NALTYPE_FILL:
Andreas Huber55f8aee2010-09-22 11:47:00 -0700526 case AVC_NALTYPE_EOSEQ:
Andreas Huber15644552010-08-04 13:04:46 -0700527 {
528 *out = new MediaBuffer(0);
529
530 err = OK;
531 break;
532 }
533
534 default:
535 {
536 LOGE("Should not be here, unknown nalType %d", nalType);
Andreas Huberb8fdab22011-03-18 11:40:20 -0700537
538 err = ERROR_MALFORMED;
Andreas Huber15644552010-08-04 13:04:46 -0700539 break;
540 }
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800541 }
Andreas Huber15644552010-08-04 13:04:46 -0700542 } else {
543 // We haven't seen SPS or PPS yet.
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800544
Andreas Huber15644552010-08-04 13:04:46 -0700545 *out = new MediaBuffer(0);
546 err = OK;
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800547 }
548
Andreas Huber94020382010-05-12 16:30:12 -0700549 if (releaseFragment) {
550 size_t offset = mInputBuffer->range_offset();
551 if (fragSize + 4 == mInputBuffer->range_length()) {
552 mInputBuffer->release();
553 mInputBuffer = NULL;
554 } else {
555 mInputBuffer->set_range(
556 offset + fragSize + 4,
557 mInputBuffer->range_length() - fragSize - 4);
558 }
559 }
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800560
Andreas Huber94020382010-05-12 16:30:12 -0700561 return err;
Andreas Huber4a0ec3f2009-12-10 09:44:29 -0800562}
563
564// static
565int32_t AVCDecoder::ActivateSPSWrapper(
566 void *userData, unsigned int sizeInMbs, unsigned int numBuffers) {
567 return static_cast<AVCDecoder *>(userData)->activateSPS(sizeInMbs, numBuffers);
568}
569
570// static
571int32_t AVCDecoder::BindFrameWrapper(
572 void *userData, int32_t index, uint8_t **yuv) {
573 return static_cast<AVCDecoder *>(userData)->bindFrame(index, yuv);
574}
575
576// static
577void AVCDecoder::UnbindFrame(void *userData, int32_t index) {
578}
579
580int32_t AVCDecoder::activateSPS(
581 unsigned int sizeInMbs, unsigned int numBuffers) {
582 CHECK(mFrames.isEmpty());
583
584 size_t frameSize = (sizeInMbs << 7) * 3;
585 for (unsigned int i = 0; i < numBuffers; ++i) {
586 MediaBuffer *buffer = new MediaBuffer(frameSize);
587 buffer->setObserver(this);
588
589 mFrames.push(buffer);
590 }
591
592 return 1;
593}
594
595int32_t AVCDecoder::bindFrame(int32_t index, uint8_t **yuv) {
596 CHECK(index >= 0);
597 CHECK(index < (int32_t)mFrames.size());
598
599 CHECK(mInputBuffer != NULL);
600 int64_t timeUs;
601 CHECK(mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
602 mFrames[index]->meta_data()->setInt64(kKeyTime, timeUs);
603
604 *yuv = (uint8_t *)mFrames[index]->data();
605
606 return 1;
607}
608
609void AVCDecoder::releaseFrames() {
610 for (size_t i = 0; i < mFrames.size(); ++i) {
611 MediaBuffer *buffer = mFrames.editItemAt(i);
612
613 buffer->setObserver(NULL);
614 buffer->release();
615 }
616 mFrames.clear();
617}
618
619void AVCDecoder::signalBufferReturned(MediaBuffer *buffer) {
620}
621
622} // namespace android