• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016, 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 #include <gui/Surface.h>
18 
19 #include <media/ICrypto.h>
20 #include <media/stagefright/foundation/ABuffer.h>
21 #include <media/stagefright/foundation/ALooper.h>
22 #include <media/stagefright/foundation/AMessage.h>
23 #include <media/stagefright/foundation/AUtils.h>
24 #include <media/stagefright/MediaBuffer.h>
25 #include <media/stagefright/MediaCodecList.h>
26 #include <media/stagefright/MediaCodec.h>
27 #include <media/stagefright/MetaData.h>
28 #include <media/stagefright/SimpleDecodingSource.h>
29 #include <media/stagefright/Utils.h>
30 
31 using namespace android;
32 
33 const int64_t kTimeoutWaitForOutputUs = 500000; // 0.5 seconds
34 const int64_t kTimeoutWaitForInputUs = 5000; // 5 milliseconds
35 
36 //static
Create(const sp<IMediaSource> & source,uint32_t flags,const sp<ANativeWindow> & nativeWindow,const char * desiredCodec)37 sp<SimpleDecodingSource> SimpleDecodingSource::Create(
38         const sp<IMediaSource> &source, uint32_t flags, const sp<ANativeWindow> &nativeWindow,
39         const char *desiredCodec) {
40     sp<Surface> surface = static_cast<Surface*>(nativeWindow.get());
41     const char *mime = NULL;
42     sp<MetaData> meta = source->getFormat();
43     CHECK(meta->findCString(kKeyMIMEType, &mime));
44 
45     sp<AMessage> format = new AMessage;
46     if (convertMetaDataToMessage(source->getFormat(), &format) != OK) {
47         return NULL;
48     }
49 
50     Vector<AString> matchingCodecs;
51     MediaCodecList::findMatchingCodecs(
52             mime, false /* encoder */, flags, &matchingCodecs);
53 
54     sp<ALooper> looper = new ALooper;
55     looper->setName("stagefright");
56     looper->start();
57 
58     sp<MediaCodec> codec;
59 
60     for (size_t i = 0; i < matchingCodecs.size(); ++i) {
61         const AString &componentName = matchingCodecs[i];
62         if (desiredCodec != NULL && componentName.compare(desiredCodec)) {
63             continue;
64         }
65 
66         ALOGV("Attempting to allocate codec '%s'", componentName.c_str());
67 
68         codec = MediaCodec::CreateByComponentName(looper, componentName);
69         if (codec != NULL) {
70             ALOGI("Successfully allocated codec '%s'", componentName.c_str());
71 
72             status_t err = codec->configure(format, surface, NULL /* crypto */, 0 /* flags */);
73             if (err == OK) {
74                 err = codec->getOutputFormat(&format);
75             }
76             if (err == OK) {
77                 return new SimpleDecodingSource(codec, source, looper, surface != NULL, format);
78             }
79 
80             ALOGD("Failed to configure codec '%s'", componentName.c_str());
81             codec->release();
82             codec = NULL;
83         }
84     }
85 
86     looper->stop();
87     ALOGE("No matching decoder! (mime: %s)", mime);
88     return NULL;
89 }
90 
SimpleDecodingSource(const sp<MediaCodec> & codec,const sp<IMediaSource> & source,const sp<ALooper> & looper,bool usingSurface,const sp<AMessage> & format)91 SimpleDecodingSource::SimpleDecodingSource(
92         const sp<MediaCodec> &codec, const sp<IMediaSource> &source, const sp<ALooper> &looper,
93         bool usingSurface, const sp<AMessage> &format)
94     : mCodec(codec),
95       mSource(source),
96       mLooper(looper),
97       mUsingSurface(usingSurface),
98       mProtectedState(format) {
99     mCodec->getName(&mComponentName);
100 }
101 
~SimpleDecodingSource()102 SimpleDecodingSource::~SimpleDecodingSource() {
103     mCodec->release();
104     mLooper->stop();
105 }
106 
start(MetaData * params)107 status_t SimpleDecodingSource::start(MetaData *params) {
108     (void)params;
109     Mutexed<ProtectedState>::Locked me(mProtectedState);
110     if (me->mState != INIT) {
111         return -EINVAL;
112     }
113     status_t res = mCodec->start();
114     if (res == OK) {
115         res = mSource->start();
116     }
117 
118     if (res == OK) {
119         me->mState = STARTED;
120         me->mQueuedInputEOS = false;
121         me->mGotOutputEOS = false;
122     } else {
123         me->mState = ERROR;
124     }
125 
126     return res;
127 }
128 
stop()129 status_t SimpleDecodingSource::stop() {
130     Mutexed<ProtectedState>::Locked me(mProtectedState);
131     if (me->mState != STARTED) {
132         return -EINVAL;
133     }
134 
135     // wait for any pending reads to complete
136     me->mState = STOPPING;
137     while (me->mReading) {
138         me.waitForCondition(me->mReadCondition);
139     }
140 
141     status_t res1 = mCodec->stop();
142     if (res1 != OK) {
143         mCodec->release();
144     }
145     status_t res2 = mSource->stop();
146     if (res1 == OK && res2 == OK) {
147         me->mState = STOPPED;
148     } else {
149         me->mState = ERROR;
150     }
151     return res1 != OK ? res1 : res2;
152 }
153 
getFormat()154 sp<MetaData> SimpleDecodingSource::getFormat() {
155     Mutexed<ProtectedState>::Locked me(mProtectedState);
156     if (me->mState == STARTED || me->mState == INIT) {
157         sp<MetaData> meta = new MetaData();
158         convertMessageToMetaData(me->mFormat, meta);
159         return meta;
160     }
161     return NULL;
162 }
163 
ProtectedState(const sp<AMessage> & format)164 SimpleDecodingSource::ProtectedState::ProtectedState(const sp<AMessage> &format)
165     : mReading(false),
166       mFormat(format),
167       mState(INIT),
168       mQueuedInputEOS(false),
169       mGotOutputEOS(false) {
170 }
171 
read(MediaBuffer ** buffer,const ReadOptions * options)172 status_t SimpleDecodingSource::read(
173         MediaBuffer **buffer, const ReadOptions *options) {
174     *buffer = NULL;
175 
176     Mutexed<ProtectedState>::Locked me(mProtectedState);
177     if (me->mState != STARTED) {
178         return ERROR_END_OF_STREAM;
179     }
180     me->mReading = true;
181 
182     status_t res = doRead(me, buffer, options);
183 
184     me.lock();
185     me->mReading = false;
186     if (me->mState != STARTED) {
187         me->mReadCondition.signal();
188     }
189 
190     return res;
191 }
192 
doRead(Mutexed<ProtectedState>::Locked & me,MediaBuffer ** buffer,const ReadOptions * options)193 status_t SimpleDecodingSource::doRead(
194         Mutexed<ProtectedState>::Locked &me, MediaBuffer **buffer, const ReadOptions *options) {
195     // |me| is always locked on entry, but is allowed to be unlocked on exit
196     CHECK_EQ(me->mState, STARTED);
197 
198     size_t out_ix, in_ix, out_offset, out_size;
199     int64_t out_pts;
200     uint32_t out_flags;
201     status_t res;
202 
203     // flush codec on seek
204     IMediaSource::ReadOptions::SeekMode mode;
205     if (options != NULL && options->getSeekTo(&out_pts, &mode)) {
206         me->mQueuedInputEOS = false;
207         me->mGotOutputEOS = false;
208         mCodec->flush();
209     }
210 
211     if (me->mGotOutputEOS) {
212         return ERROR_END_OF_STREAM;
213     }
214 
215     for (int retries = 0; ++retries; ) {
216         // If we fill all available input buffers, we should expect that
217         // the codec produces at least one output buffer. Also, the codec
218         // should produce an output buffer in at most 1 seconds. Retry a
219         // few times nonetheless.
220         while (!me->mQueuedInputEOS) {
221             // allow some time to get input buffer after flush
222             res = mCodec->dequeueInputBuffer(&in_ix, kTimeoutWaitForInputUs);
223             if (res == -EAGAIN) {
224                 // no available input buffers
225                 break;
226             }
227 
228             sp<ABuffer> in_buffer;
229             if (res == OK) {
230                 res = mCodec->getInputBuffer(in_ix, &in_buffer);
231             }
232 
233             if (res != OK || in_buffer == NULL) {
234                 ALOGW("[%s] could not get input buffer #%zu",
235                         mComponentName.c_str(), in_ix);
236                 me->mState = ERROR;
237                 return UNKNOWN_ERROR;
238             }
239 
240             MediaBuffer *in_buf;
241             while (true) {
242                 in_buf = NULL;
243                 me.unlock();
244                 res = mSource->read(&in_buf, options);
245                 me.lock();
246                 if (res != OK || me->mState != STARTED) {
247                     if (in_buf != NULL) {
248                         in_buf->release();
249                         in_buf = NULL;
250                     }
251 
252                     // queue EOS
253                     me->mQueuedInputEOS = true;
254                     if (mCodec->queueInputBuffer(
255                                  in_ix, 0 /* offset */, 0 /* size */,
256                                  0 /* pts */, MediaCodec::BUFFER_FLAG_EOS) != OK) {
257                         ALOGI("[%s] failed to queue input EOS", mComponentName.c_str());
258                         me->mState = ERROR;
259                         return UNKNOWN_ERROR;
260                     }
261 
262                     // don't stop on EOS, but report error or EOS on stop
263                     if (res != ERROR_END_OF_STREAM) {
264                         me->mState = ERROR;
265                         return res;
266                     }
267                     if (me->mState != STARTED) {
268                         return ERROR_END_OF_STREAM;
269                     }
270                     break;
271                 }
272                 if (in_buf == NULL) { // should not happen
273                     continue;
274                 } else if (in_buf->range_length() != 0) {
275                     break;
276                 }
277                 in_buf->release();
278             }
279 
280             if (in_buf != NULL) {
281                 int64_t timestampUs = 0;
282                 CHECK(in_buf->meta_data()->findInt64(kKeyTime, &timestampUs));
283                 if (in_buf->range_length() > in_buffer->capacity()) {
284                     ALOGW("'%s' received %zu input bytes for buffer of size %zu",
285                             mComponentName.c_str(),
286                             in_buf->range_length(), in_buffer->capacity());
287                 }
288                 memcpy(in_buffer->base(), (uint8_t *)in_buf->data() + in_buf->range_offset(),
289                        min(in_buf->range_length(), in_buffer->capacity()));
290 
291                 res = mCodec->queueInputBuffer(
292                         in_ix, 0 /* offset */, in_buf->range_length(),
293                         timestampUs, 0 /* flags */);
294                 if (res != OK) {
295                     ALOGI("[%s] failed to queue input buffer #%zu", mComponentName.c_str(), in_ix);
296                     me->mState = ERROR;
297                 }
298                 in_buf->release();
299             }
300         }
301 
302         me.unlock();
303         res = mCodec->dequeueOutputBuffer(
304                 &out_ix, &out_offset, &out_size, &out_pts,
305                 &out_flags, kTimeoutWaitForOutputUs /* timeoutUs */);
306         me.lock();
307         // abort read on stop
308         if (me->mState != STARTED) {
309             if (res == OK) {
310                 mCodec->releaseOutputBuffer(out_ix);
311             }
312             return ERROR_END_OF_STREAM;
313         }
314 
315         if (res == -EAGAIN) {
316             ALOGD("[%s] did not produce an output buffer. retry count: %d",
317                   mComponentName.c_str(), retries);
318             continue;
319         } else if (res == INFO_FORMAT_CHANGED) {
320             if (mCodec->getOutputFormat(&me->mFormat) != OK) {
321                 me->mState = ERROR;
322                 res = UNKNOWN_ERROR;
323             }
324             return res;
325         } else if (res == INFO_OUTPUT_BUFFERS_CHANGED) {
326             ALOGV("output buffers changed");
327             continue;
328         } else if (res != OK) {
329             me->mState = ERROR;
330             return res;
331         }
332 
333         sp<ABuffer> out_buffer;
334         res = mCodec->getOutputBuffer(out_ix, &out_buffer);
335         if (res != OK) {
336             ALOGW("[%s] could not get output buffer #%zu",
337                     mComponentName.c_str(), out_ix);
338             me->mState = ERROR;
339             return UNKNOWN_ERROR;
340         }
341         if (out_flags & MediaCodec::BUFFER_FLAG_EOS) {
342             me->mGotOutputEOS = true;
343             // return EOS immediately if last buffer is empty
344             if (out_size == 0) {
345                 mCodec->releaseOutputBuffer(out_ix);
346                 return ERROR_END_OF_STREAM;
347             }
348         }
349 
350         if (mUsingSurface && out_size > 0) {
351             *buffer = new MediaBuffer(0);
352             mCodec->renderOutputBufferAndRelease(out_ix);
353         } else {
354             *buffer = new MediaBuffer(out_size);
355             CHECK_LE(out_buffer->size(), (*buffer)->size());
356             memcpy((*buffer)->data(), out_buffer->data(), out_buffer->size());
357             (*buffer)->meta_data()->setInt64(kKeyTime, out_pts);
358             mCodec->releaseOutputBuffer(out_ix);
359         }
360         return OK;
361     }
362 
363     return TIMED_OUT;
364 }
365