blob: 8c6bc94d79eb7ca44e774e577c14340b16948457 [file] [log] [blame]
Ajit Khare470d0922013-01-21 01:11:06 -08001/*
2 *Copyright (c) 2013, The Linux Foundation. All rights reserved.
3 *Not a Contribution, Apache license notifications and license are retained
4 *for attribution purposes only.
5 *Copyright (C) 2010 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20#include "DashPacketSource.h"
21
22#include <media/stagefright/foundation/ABuffer.h>
23#include <media/stagefright/foundation/ADebug.h>
24#include <media/stagefright/foundation/AMessage.h>
25#include <media/stagefright/foundation/AString.h>
26#include <media/stagefright/foundation/hexdump.h>
27#include <media/stagefright/MediaBuffer.h>
28#include <media/stagefright/MediaDefs.h>
29#include <media/stagefright/MetaData.h>
30#include <utils/Vector.h>
31
32namespace android {
33
34DashPacketSource::DashPacketSource(const sp<MetaData> &meta)
35 : mIsAudio(false),
36 mFormat(meta),
37 mEOSResult(OK),
38 mStreamPID(0),
39 mProgramPID(0),
40 mFirstPTS(0) {
41 const char *mime;
42 CHECK(meta->findCString(kKeyMIMEType, &mime));
43
44 if (!strncasecmp("audio/", mime, 6)) {
45 mIsAudio = true;
46 }
47}
48
49void DashPacketSource::setFormat(const sp<MetaData> &meta) {
50 Mutex::Autolock autoLock(mLock);
51 CHECK(mFormat == NULL);
52 mFormat = meta;
53}
54
55void DashPacketSource::updateFormat(const sp<MetaData> &meta) {
56 Mutex::Autolock autoLock(mLock);
57 mFormat = meta;
58}
59
60DashPacketSource::~DashPacketSource() {
61}
62
63status_t DashPacketSource::start(MetaData *params) {
64 return OK;
65}
66
67status_t DashPacketSource::stop() {
68 return OK;
69}
70
71void DashPacketSource::setStreamInfo(unsigned streamPID, unsigned programPID, uint64_t firstPTS){
72 mStreamPID = streamPID;
73 mProgramPID = programPID;
74 mFirstPTS = firstPTS;
75}
76
77status_t DashPacketSource::getStreamInfo(unsigned& streamPID, unsigned& programPID, uint64_t& firstPTS){
78 streamPID = mStreamPID;
79 programPID = mProgramPID;
80 firstPTS = mFirstPTS;
81 return OK;
82}
83
84sp<MetaData> DashPacketSource::getFormat() {
85 Mutex::Autolock autoLock(mLock);
86 return mFormat;
87}
88
89status_t DashPacketSource::dequeueAccessUnit(sp<ABuffer> *buffer) {
90 buffer->clear();
91
92 Mutex::Autolock autoLock(mLock);
93 while (mEOSResult == OK && mBuffers.empty()) {
94 mCondition.wait(mLock);
95 }
96
97 if (!mBuffers.empty()) {
98 *buffer = *mBuffers.begin();
99 mBuffers.erase(mBuffers.begin());
100
101 int32_t discontinuity;
102 if ((*buffer)->meta()->findInt32("discontinuity", &discontinuity)) {
103 if (wasFormatChange(discontinuity)) {
104 mFormat.clear();
105 }
106
107 return INFO_DISCONTINUITY;
108 }
109
110 return OK;
111 }
112
113 return mEOSResult;
114}
115
116status_t DashPacketSource::read(
117 MediaBuffer **out, const ReadOptions *) {
118 *out = NULL;
119
120 Mutex::Autolock autoLock(mLock);
121 while (mEOSResult == OK && mBuffers.empty()) {
122 mCondition.wait(mLock);
123 }
124
125 if (!mBuffers.empty()) {
126 const sp<ABuffer> buffer = *mBuffers.begin();
127 mBuffers.erase(mBuffers.begin());
128
129 int32_t discontinuity;
130 if (buffer->meta()->findInt32("discontinuity", &discontinuity)) {
131 if (wasFormatChange(discontinuity)) {
132 mFormat.clear();
133 }
134
135 return INFO_DISCONTINUITY;
136 } else {
137 int64_t timeUs;
138 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
139
140 MediaBuffer *mediaBuffer = new MediaBuffer(buffer);
141
142 mediaBuffer->meta_data()->setInt64(kKeyTime, timeUs);
143
144 *out = mediaBuffer;
145 return OK;
146 }
147 }
148
149 return mEOSResult;
150}
151
152bool DashPacketSource::wasFormatChange(
153 int32_t discontinuityType) const {
154 if (mIsAudio) {
155 return (discontinuityType & ATSParser::DISCONTINUITY_AUDIO_FORMAT) != 0;
156 }
157
158 return (discontinuityType & ATSParser::DISCONTINUITY_VIDEO_FORMAT) != 0;
159}
160
161void DashPacketSource::queueAccessUnit(const sp<ABuffer> &buffer) {
162 int32_t damaged;
163 if (buffer->meta()->findInt32("damaged", &damaged) && damaged) {
164 // LOG(VERBOSE) << "discarding damaged AU";
165 return;
166 }
167
168 int64_t timeUs;
169 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
170 ALOGV("queueAccessUnit timeUs=%lld us (%.2f secs)", timeUs, timeUs / 1E6);
171
172 Mutex::Autolock autoLock(mLock);
173 mBuffers.push_back(buffer);
174 ALOGV("@@@@:: DashPacketSource --> size is %d ",mBuffers.size() );
175 mCondition.signal();
176}
177
178int DashPacketSource::getQueueSize() {
179 return mBuffers.size();
180}
181
182void DashPacketSource::queueDiscontinuity(
183 ATSParser::DiscontinuityType type,
184 const sp<AMessage> &extra) {
185 Mutex::Autolock autoLock(mLock);
186
187 if (type == ATSParser::DISCONTINUITY_SEEK ||
188 type == ATSParser::DISCONTINUITY_SEEK) {
189 ALOGI("Flushing all Access units for seek");
190 mBuffers.clear();
191 mEOSResult = OK;
192 mCondition.signal();
193 return;
194 }
195
196 // Leave only discontinuities in the queue.
197 List<sp<ABuffer> >::iterator it = mBuffers.begin();
198 while (it != mBuffers.end()) {
199 sp<ABuffer> oldBuffer = *it;
200
201 int32_t oldDiscontinuityType;
202 if (!oldBuffer->meta()->findInt32(
203 "discontinuity", &oldDiscontinuityType)) {
204 it = mBuffers.erase(it);
205 continue;
206 }
207
208 ++it;
209 }
210
211 mEOSResult = OK;
212
213 sp<ABuffer> buffer = new ABuffer(0);
214 buffer->meta()->setInt32("discontinuity", static_cast<int32_t>(type));
215 buffer->meta()->setMessage("extra", extra);
216
217 mBuffers.push_back(buffer);
218 mCondition.signal();
219}
220
221void DashPacketSource::signalEOS(status_t result) {
222 CHECK(result != OK);
223
224 Mutex::Autolock autoLock(mLock);
225 mEOSResult = result;
226 mCondition.signal();
227}
228
229bool DashPacketSource::hasBufferAvailable(status_t *finalResult) {
230 Mutex::Autolock autoLock(mLock);
231 if (!mBuffers.empty()) {
232 return true;
233 }
234
235 *finalResult = mEOSResult;
236 return false;
237}
238
239int64_t DashPacketSource::getBufferedDurationUs(status_t *finalResult) {
240 Mutex::Autolock autoLock(mLock);
241
242 *finalResult = mEOSResult;
243
244 if (mBuffers.empty()) {
245 return 0;
246 }
247
248 int64_t time1 = -1;
249 int64_t time2 = -1;
250
251 List<sp<ABuffer> >::iterator it = mBuffers.begin();
252 while (it != mBuffers.end()) {
253 const sp<ABuffer> &buffer = *it;
254
255 int64_t timeUs;
256 if (buffer->meta()->findInt64("timeUs", &timeUs)) {
257 if (time1 < 0) {
258 time1 = timeUs;
259 }
260
261 time2 = timeUs;
262 } else {
263 // This is a discontinuity, reset everything.
264 time1 = time2 = -1;
265 }
266
267 ++it;
268 }
269
270 return time2 - time1;
271}
272
273status_t DashPacketSource::nextBufferTime(int64_t *timeUs) {
274 *timeUs = 0;
275
276 Mutex::Autolock autoLock(mLock);
277
278 if (mBuffers.empty()) {
279 return mEOSResult != OK ? mEOSResult : -EWOULDBLOCK;
280 }
281
282 sp<ABuffer> buffer = *mBuffers.begin();
283 CHECK(buffer->meta()->findInt64("timeUs", timeUs));
284 return OK;
285}
286
287status_t DashPacketSource::nextBufferIsSync(bool* isSyncFrame) {
288 Mutex::Autolock autoLock(mLock);
289 CHECK(isSyncFrame != NULL);
290
291 if (mBuffers.empty()) {
292 return mEOSResult != OK ? mEOSResult : -EWOULDBLOCK;
293 }
294
295 sp<ABuffer> buffer = *mBuffers.begin();
296
297 *isSyncFrame = false;
298 int32_t value = 0;
299 if (buffer->meta()->findInt32("isSync", &value) && (value == 1)) {
300 *isSyncFrame = true;
301 }
302 return OK;
303}
304
305} // namespace android