1 /*
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
17 #include <mutex>
18
19 #include <media/stagefright/foundation/ABuffer.h>
20 #include <media/stagefright/foundation/AMessage.h>
21 #include <media/stagefright/Utils.h>
22
23 #include <media/MediaTrack.h>
24 #include <media/MediaExtractorPluginApi.h>
25 #include <media/NdkMediaErrorPriv.h>
26 #include <media/NdkMediaFormatPriv.h>
27
28 namespace android {
29
MediaTrack()30 MediaTrack::MediaTrack() {}
31
~MediaTrack()32 MediaTrack::~MediaTrack() {}
33
34 ////////////////////////////////////////////////////////////////////////////////
35
setNonBlocking()36 void MediaTrack::ReadOptions::setNonBlocking() {
37 mNonBlocking = true;
38 }
39
clearNonBlocking()40 void MediaTrack::ReadOptions::clearNonBlocking() {
41 mNonBlocking = false;
42 }
43
getNonBlocking() const44 bool MediaTrack::ReadOptions::getNonBlocking() const {
45 return mNonBlocking;
46 }
47
setSeekTo(int64_t time_us,SeekMode mode)48 void MediaTrack::ReadOptions::setSeekTo(int64_t time_us, SeekMode mode) {
49 mOptions |= kSeekTo_Option;
50 mSeekTimeUs = time_us;
51 mSeekMode = mode;
52 }
53
getSeekTo(int64_t * time_us,SeekMode * mode) const54 bool MediaTrack::ReadOptions::getSeekTo(
55 int64_t *time_us, SeekMode *mode) const {
56 *time_us = mSeekTimeUs;
57 *mode = mSeekMode;
58 return (mOptions & kSeekTo_Option) != 0;
59 }
60
61 /* -------------- unwrapper --------------- */
62
MediaTrackCUnwrapper(CMediaTrack * cmediatrack)63 MediaTrackCUnwrapper::MediaTrackCUnwrapper(CMediaTrack *cmediatrack) {
64 wrapper = cmediatrack;
65 bufferGroup = nullptr;
66 }
67
create(CMediaTrack * cmediatrack)68 MediaTrackCUnwrapper *MediaTrackCUnwrapper::create(CMediaTrack *cmediatrack) {
69 if (cmediatrack == nullptr) {
70 return nullptr;
71 }
72 return new MediaTrackCUnwrapper(cmediatrack);
73 }
74
~MediaTrackCUnwrapper()75 MediaTrackCUnwrapper::~MediaTrackCUnwrapper() {
76 wrapper->free(wrapper->data);
77 free(wrapper);
78 delete bufferGroup;
79 }
80
start()81 status_t MediaTrackCUnwrapper::start() {
82 if (bufferGroup == nullptr) {
83 bufferGroup = new MediaBufferGroup();
84 }
85 return reverse_translate_error(wrapper->start(wrapper->data, bufferGroup->wrap()));
86 }
87
stop()88 status_t MediaTrackCUnwrapper::stop() {
89 return reverse_translate_error(wrapper->stop(wrapper->data));
90 }
91
getFormat(MetaDataBase & format)92 status_t MediaTrackCUnwrapper::getFormat(MetaDataBase& format) {
93 sp<AMessage> msg = new AMessage();
94 AMediaFormat *tmpFormat = AMediaFormat_fromMsg(&msg);
95 media_status_t ret = wrapper->getFormat(wrapper->data, tmpFormat);
96 sp<MetaData> newMeta = new MetaData();
97 convertMessageToMetaData(msg, newMeta);
98 delete tmpFormat;
99 format = *newMeta;
100 return reverse_translate_error(ret);
101 }
102
read(MediaBufferBase ** buffer,const ReadOptions * options)103 status_t MediaTrackCUnwrapper::read(MediaBufferBase **buffer, const ReadOptions *options) {
104
105 uint32_t opts = 0;
106
107 if (options && options->getNonBlocking()) {
108 opts |= CMediaTrackReadOptions::NONBLOCKING;
109 }
110
111 int64_t seekPosition = 0;
112 MediaTrack::ReadOptions::SeekMode seekMode;
113 if (options && options->getSeekTo(&seekPosition, &seekMode)) {
114 opts |= SEEK;
115 opts |= (uint32_t) seekMode;
116 }
117 CMediaBuffer *buf = nullptr;
118 media_status_t ret = wrapper->read(wrapper->data, &buf, opts, seekPosition);
119 if (ret == AMEDIA_OK && buf != nullptr) {
120 *buffer = (MediaBufferBase*)buf->handle;
121 MetaDataBase &meta = (*buffer)->meta_data();
122 AMediaFormat *format = buf->meta_data(buf->handle);
123 // only convert the keys we're actually expecting, as doing
124 // the full convertMessageToMetadata() for every buffer is
125 // too expensive
126 int64_t val64;
127 if (format->mFormat->findInt64("timeUs", &val64)) {
128 meta.setInt64(kKeyTime, val64);
129 }
130 if (format->mFormat->findInt64("durationUs", &val64)) {
131 meta.setInt64(kKeyDuration, val64);
132 }
133 if (format->mFormat->findInt64("target-time", &val64)) {
134 meta.setInt64(kKeyTargetTime, val64);
135 }
136 int32_t val32;
137 if (format->mFormat->findInt32("is-sync-frame", &val32)) {
138 meta.setInt32(kKeyIsSyncFrame, val32);
139 }
140 if (format->mFormat->findInt32("temporal-layer-id", &val32)) {
141 meta.setInt32(kKeyTemporalLayerId, val32);
142 }
143 if (format->mFormat->findInt32("temporal-layer-count", &val32)) {
144 meta.setInt32(kKeyTemporalLayerCount, val32);
145 }
146 if (format->mFormat->findInt32("crypto-default-iv-size", &val32)) {
147 meta.setInt32(kKeyCryptoDefaultIVSize, val32);
148 }
149 if (format->mFormat->findInt32("crypto-mode", &val32)) {
150 meta.setInt32(kKeyCryptoMode, val32);
151 }
152 if (format->mFormat->findInt32("crypto-encrypted-byte-block", &val32)) {
153 meta.setInt32(kKeyEncryptedByteBlock, val32);
154 }
155 if (format->mFormat->findInt32("crypto-skip-byte-block", &val32)) {
156 meta.setInt32(kKeySkipByteBlock, val32);
157 }
158 if (format->mFormat->findInt32("valid-samples", &val32)) {
159 meta.setInt32(kKeyValidSamples, val32);
160 }
161 sp<ABuffer> valbuf;
162 if (format->mFormat->findBuffer("crypto-plain-sizes", &valbuf)) {
163 meta.setData(kKeyPlainSizes,
164 MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
165 }
166 if (format->mFormat->findBuffer("crypto-encrypted-sizes", &valbuf)) {
167 meta.setData(kKeyEncryptedSizes,
168 MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
169 }
170 if (format->mFormat->findBuffer("crypto-key", &valbuf)) {
171 meta.setData(kKeyCryptoKey,
172 MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
173 }
174 if (format->mFormat->findBuffer("crypto-iv", &valbuf)) {
175 meta.setData(kKeyCryptoIV,
176 MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
177 }
178 if (format->mFormat->findBuffer("sei", &valbuf)) {
179 meta.setData(kKeySEI,
180 MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
181 }
182 if (format->mFormat->findBuffer("audio-presentation-info", &valbuf)) {
183 meta.setData(kKeyAudioPresentationInfo,
184 MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
185 }
186 } else {
187 *buffer = nullptr;
188 }
189
190 return reverse_translate_error(ret);
191 }
192
supportNonblockingRead()193 bool MediaTrackCUnwrapper::supportNonblockingRead() {
194 return wrapper->supportsNonBlockingRead(wrapper->data);
195 }
196
197 } // namespace android
198