blob: b53252d4ff305f7038e5829884dda9dca3d5d28e [file] [log] [blame]
Andreas Huber94a483b2013-01-29 09:22:16 -08001/*
2 * Copyright 2012, 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 "DirectRenderer"
19#include <utils/Log.h>
20
21#include "DirectRenderer.h"
22
Andreas Huber94a483b2013-01-29 09:22:16 -080023#include <gui/SurfaceComposerClient.h>
Mathias Agopian1a2952a2013-02-14 17:11:27 -080024#include <gui/Surface.h>
Andreas Huber94a483b2013-01-29 09:22:16 -080025#include <media/ICrypto.h>
26#include <media/stagefright/foundation/ABuffer.h>
27#include <media/stagefright/foundation/ADebug.h>
28#include <media/stagefright/foundation/AMessage.h>
Andreas Hubera556c482013-03-05 10:56:27 -080029#include <media/stagefright/foundation/hexdump.h>
Andreas Huber94a483b2013-01-29 09:22:16 -080030#include <media/stagefright/MediaCodec.h>
31#include <media/stagefright/MediaErrors.h>
32#include <media/stagefright/MetaData.h>
33#include <media/stagefright/Utils.h>
34
35namespace android {
36
Andreas Huber94a483b2013-01-29 09:22:16 -080037DirectRenderer::DirectRenderer(
Andreas Huber94a483b2013-01-29 09:22:16 -080038 const sp<IGraphicBufferProducer> &bufferProducer)
Andreas Hubera556c482013-03-05 10:56:27 -080039 : mSurfaceTex(bufferProducer),
Andreas Huber94a483b2013-01-29 09:22:16 -080040 mVideoDecoderNotificationPending(false),
Andreas Hubera556c482013-03-05 10:56:27 -080041 mRenderPending(false),
42 mFirstRenderTimeUs(-1ll),
43 mFirstRenderRealUs(-1ll) {
Andreas Huber94a483b2013-01-29 09:22:16 -080044}
45
46DirectRenderer::~DirectRenderer() {
47 if (mVideoDecoder != NULL) {
48 mVideoDecoder->release();
49 mVideoDecoder.clear();
50
51 mVideoDecoderLooper->stop();
52 mVideoDecoderLooper.clear();
53 }
54}
55
56void DirectRenderer::onMessageReceived(const sp<AMessage> &msg) {
57 switch (msg->what()) {
Andreas Huber94a483b2013-01-29 09:22:16 -080058 case kWhatVideoDecoderNotify:
59 {
60 onVideoDecoderNotify();
61 break;
62 }
63
Andreas Hubera556c482013-03-05 10:56:27 -080064 case kWhatRender:
65 {
66 onRender();
67 break;
68 }
69
Andreas Huber94a483b2013-01-29 09:22:16 -080070 default:
71 TRESPASS();
72 }
73}
74
Andreas Hubera556c482013-03-05 10:56:27 -080075void DirectRenderer::setFormat(
76 size_t trackIndex, const sp<AMessage> &format) {
77 if (trackIndex == 1) {
78 // Ignore audio for now.
Andreas Huber94a483b2013-01-29 09:22:16 -080079 return;
80 }
81
Andreas Hubera556c482013-03-05 10:56:27 -080082 CHECK(mVideoDecoder == NULL);
83
84 AString mime;
85 CHECK(format->findString("mime", &mime));
86
87 mVideoDecoderLooper = new ALooper;
88 mVideoDecoderLooper->setName("video codec looper");
89
90 mVideoDecoderLooper->start(
91 false /* runOnCallingThread */,
92 false /* canCallJava */,
93 PRIORITY_DEFAULT);
94
95 mVideoDecoder = MediaCodec::CreateByType(
96 mVideoDecoderLooper, mime.c_str(), false /* encoder */);
97
98 CHECK(mVideoDecoder != NULL);
99
100 status_t err = mVideoDecoder->configure(
101 format,
102 mSurfaceTex == NULL
103 ? NULL : new Surface(mSurfaceTex),
104 NULL /* crypto */,
105 0 /* flags */);
106 CHECK_EQ(err, (status_t)OK);
107
108 err = mVideoDecoder->start();
109 CHECK_EQ(err, (status_t)OK);
110
111 err = mVideoDecoder->getInputBuffers(
112 &mVideoDecoderInputBuffers);
113 CHECK_EQ(err, (status_t)OK);
114
115 scheduleVideoDecoderNotification();
116}
117
118void DirectRenderer::queueAccessUnit(
119 size_t trackIndex, const sp<ABuffer> &accessUnit) {
120 if (trackIndex == 1) {
121 // Ignore audio for now.
Andreas Huber94a483b2013-01-29 09:22:16 -0800122 return;
123 }
124
Andreas Hubera556c482013-03-05 10:56:27 -0800125 if (mVideoDecoder == NULL) {
126 sp<AMessage> format = new AMessage;
127 format->setString("mime", "video/avc");
128 format->setInt32("width", 640);
129 format->setInt32("height", 360);
Andreas Huber94a483b2013-01-29 09:22:16 -0800130
Andreas Hubera556c482013-03-05 10:56:27 -0800131 setFormat(0, format);
Andreas Huber94a483b2013-01-29 09:22:16 -0800132 }
133
Andreas Hubera556c482013-03-05 10:56:27 -0800134 mVideoAccessUnits.push_back(accessUnit);
135 queueVideoDecoderInputBuffers();
Andreas Huber94a483b2013-01-29 09:22:16 -0800136}
137
138void DirectRenderer::queueVideoDecoderInputBuffers() {
139 if (mVideoDecoder == NULL) {
140 return;
141 }
142
143 bool submittedMore = false;
144
145 while (!mVideoAccessUnits.empty()
146 && !mVideoDecoderInputBuffersAvailable.empty()) {
147 size_t index = *mVideoDecoderInputBuffersAvailable.begin();
148
149 mVideoDecoderInputBuffersAvailable.erase(
150 mVideoDecoderInputBuffersAvailable.begin());
151
152 sp<ABuffer> srcBuffer = *mVideoAccessUnits.begin();
153 mVideoAccessUnits.erase(mVideoAccessUnits.begin());
154
155 const sp<ABuffer> &dstBuffer =
156 mVideoDecoderInputBuffers.itemAt(index);
157
158 memcpy(dstBuffer->data(), srcBuffer->data(), srcBuffer->size());
159
160 int64_t timeUs;
161 CHECK(srcBuffer->meta()->findInt64("timeUs", &timeUs));
162
163 status_t err = mVideoDecoder->queueInputBuffer(
164 index,
165 0 /* offset */,
166 srcBuffer->size(),
167 timeUs,
168 0 /* flags */);
169 CHECK_EQ(err, (status_t)OK);
170
171 submittedMore = true;
172 }
173
174 if (submittedMore) {
175 scheduleVideoDecoderNotification();
176 }
177}
178
179void DirectRenderer::onVideoDecoderNotify() {
180 mVideoDecoderNotificationPending = false;
181
182 for (;;) {
183 size_t index;
184 status_t err = mVideoDecoder->dequeueInputBuffer(&index);
185
186 if (err == OK) {
187 mVideoDecoderInputBuffersAvailable.push_back(index);
188 } else if (err == -EAGAIN) {
189 break;
190 } else {
191 TRESPASS();
192 }
193 }
194
195 queueVideoDecoderInputBuffers();
196
197 for (;;) {
198 size_t index;
199 size_t offset;
200 size_t size;
201 int64_t timeUs;
202 uint32_t flags;
203 status_t err = mVideoDecoder->dequeueOutputBuffer(
204 &index,
205 &offset,
206 &size,
207 &timeUs,
208 &flags);
209
210 if (err == OK) {
Andreas Hubera556c482013-03-05 10:56:27 -0800211 queueOutputBuffer(index, timeUs);
Andreas Huber94a483b2013-01-29 09:22:16 -0800212 } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) {
213 // We don't care.
214 } else if (err == INFO_FORMAT_CHANGED) {
215 // We don't care.
216 } else if (err == -EAGAIN) {
217 break;
218 } else {
219 TRESPASS();
220 }
221 }
222
223 scheduleVideoDecoderNotification();
224}
225
Andreas Hubera556c482013-03-05 10:56:27 -0800226void DirectRenderer::queueOutputBuffer(size_t index, int64_t timeUs) {
227#if 0
228 OutputInfo info;
229 info.mIndex = index;
230 info.mTimeUs = timeUs;
231 mOutputBuffers.push_back(info);
232
233 scheduleRenderIfNecessary();
234#else
235 status_t err = mVideoDecoder->renderOutputBufferAndRelease(index);
236 CHECK_EQ(err, (status_t)OK);
237#endif
238}
239
240void DirectRenderer::scheduleRenderIfNecessary() {
241 if (mRenderPending || mOutputBuffers.empty()) {
242 return;
243 }
244
245 mRenderPending = true;
246
247 int64_t timeUs = (*mOutputBuffers.begin()).mTimeUs;
248 int64_t nowUs = ALooper::GetNowUs();
249
250 if (mFirstRenderTimeUs < 0ll) {
251 mFirstRenderTimeUs = timeUs;
252 mFirstRenderRealUs = nowUs;
253 }
254
255 int64_t whenUs = timeUs - mFirstRenderTimeUs + mFirstRenderRealUs;
256 int64_t delayUs = whenUs - nowUs;
257
258 (new AMessage(kWhatRender, id()))->post(delayUs);
259}
260
261void DirectRenderer::onRender() {
262 mRenderPending = false;
263
264 int64_t nowUs = ALooper::GetNowUs();
265
266 while (!mOutputBuffers.empty()) {
267 const OutputInfo &info = *mOutputBuffers.begin();
268
269 if (info.mTimeUs > nowUs) {
270 break;
271 }
272
273 status_t err = mVideoDecoder->renderOutputBufferAndRelease(info.mIndex);
274 CHECK_EQ(err, (status_t)OK);
275
276 mOutputBuffers.erase(mOutputBuffers.begin());
277 }
278
279 scheduleRenderIfNecessary();
280}
281
Andreas Huber94a483b2013-01-29 09:22:16 -0800282void DirectRenderer::scheduleVideoDecoderNotification() {
283 if (mVideoDecoderNotificationPending) {
284 return;
285 }
286
287 sp<AMessage> notify =
288 new AMessage(kWhatVideoDecoderNotify, id());
289
290 mVideoDecoder->requestActivityNotification(notify);
291 mVideoDecoderNotificationPending = true;
292}
293
294} // namespace android
295