• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 #include "MP4Source.h"
18 
19 #include "FragmentedMP4Parser.h"
20 #include "../NuPlayerStreamListener.h"
21 
22 #include <media/IStreamSource.h>
23 #include <media/stagefright/foundation/AMessage.h>
24 #include <media/stagefright/MediaErrors.h>
25 #include <media/stagefright/MetaData.h>
26 
27 namespace android {
28 
29 struct StreamSource : public FragmentedMP4Parser::Source {
StreamSourceandroid::StreamSource30     StreamSource(const sp<IStreamSource> &source)
31         : mListener(new NuPlayer::NuPlayerStreamListener(source, 0)),
32           mPosition(0) {
33         mListener->start();
34     }
35 
readAtandroid::StreamSource36     virtual ssize_t readAt(off64_t offset, void *data, size_t size) {
37         if (offset < mPosition) {
38             return -EPIPE;
39         }
40 
41         while (offset > mPosition) {
42             char buffer[1024];
43             off64_t skipBytes = offset - mPosition;
44             if (skipBytes > sizeof(buffer)) {
45                 skipBytes = sizeof(buffer);
46             }
47 
48             sp<AMessage> extra;
49             ssize_t n;
50             for (;;) {
51                 n = mListener->read(buffer, skipBytes, &extra);
52 
53                 if (n == -EWOULDBLOCK) {
54                     usleep(10000);
55                     continue;
56                 }
57 
58                 break;
59             }
60 
61             ALOGV("skipped %ld bytes at offset %lld", n, mPosition);
62 
63             if (n < 0) {
64                 return n;
65             }
66 
67             mPosition += n;
68         }
69 
70         sp<AMessage> extra;
71         size_t total = 0;
72         while (total < size) {
73             ssize_t n = mListener->read(
74                     (uint8_t *)data + total, size - total, &extra);
75 
76             if (n == -EWOULDBLOCK) {
77                 usleep(10000);
78                 continue;
79             } else if (n == 0) {
80                 break;
81             } else if (n < 0) {
82                 mPosition += total;
83                 return n;
84             }
85 
86             total += n;
87         }
88 
89         ALOGV("read %ld bytes at offset %lld", n, mPosition);
90 
91         mPosition += total;
92 
93         return total;
94     }
95 
isSeekableandroid::StreamSource96     bool isSeekable() {
97         return false;
98     }
99 
100 private:
101     sp<NuPlayer::NuPlayerStreamListener> mListener;
102     off64_t mPosition;
103 
104     DISALLOW_EVIL_CONSTRUCTORS(StreamSource);
105 };
106 
MP4Source(const sp<IStreamSource> & source)107 MP4Source::MP4Source(const sp<IStreamSource> &source)
108     : mSource(source),
109       mLooper(new ALooper),
110       mParser(new FragmentedMP4Parser),
111       mEOS(false) {
112     mLooper->registerHandler(mParser);
113 }
114 
~MP4Source()115 MP4Source::~MP4Source() {
116 }
117 
start()118 void MP4Source::start() {
119     mLooper->start(false /* runOnCallingThread */);
120     mParser->start(new StreamSource(mSource));
121 }
122 
feedMoreTSData()123 status_t MP4Source::feedMoreTSData() {
124     return mEOS ? ERROR_END_OF_STREAM : (status_t)OK;
125 }
126 
getFormat(bool audio)127 sp<AMessage> MP4Source::getFormat(bool audio) {
128     return mParser->getFormat(audio);
129 }
130 
dequeueAccessUnit(bool audio,sp<ABuffer> * accessUnit)131 status_t MP4Source::dequeueAccessUnit(
132         bool audio, sp<ABuffer> *accessUnit) {
133     return mParser->dequeueAccessUnit(audio, accessUnit);
134 }
135 
flags() const136 uint32_t MP4Source::flags() const {
137     return 0;
138 }
139 
140 }  // namespace android
141