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 30 MediaTrack::MediaTrack() {} 31 32 MediaTrack::~MediaTrack() {} 33 34 //////////////////////////////////////////////////////////////////////////////// 35 36 void MediaTrack::ReadOptions::setNonBlocking() { 37 mNonBlocking = true; 38 } 39 40 void MediaTrack::ReadOptions::clearNonBlocking() { 41 mNonBlocking = false; 42 } 43 44 bool MediaTrack::ReadOptions::getNonBlocking() const { 45 return mNonBlocking; 46 } 47 48 void MediaTrack::ReadOptions::setSeekTo(int64_t time_us, SeekMode mode) { 49 mOptions |= kSeekTo_Option; 50 mSeekTimeUs = time_us; 51 mSeekMode = mode; 52 } 53 54 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 63 MediaTrackCUnwrapper::MediaTrackCUnwrapper(CMediaTrack *cmediatrack) { 64 wrapper = cmediatrack; 65 bufferGroup = nullptr; 66 } 67 68 MediaTrackCUnwrapper *MediaTrackCUnwrapper::create(CMediaTrack *cmediatrack) { 69 if (cmediatrack == nullptr) { 70 return nullptr; 71 } 72 return new MediaTrackCUnwrapper(cmediatrack); 73 } 74 75 MediaTrackCUnwrapper::~MediaTrackCUnwrapper() { 76 wrapper->free(wrapper->data); 77 free(wrapper); 78 delete bufferGroup; 79 } 80 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 88 status_t MediaTrackCUnwrapper::stop() { 89 return reverse_translate_error(wrapper->stop(wrapper->data)); 90 } 91 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 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 193 bool MediaTrackCUnwrapper::supportNonblockingRead() { 194 return wrapper->supportsNonBlockingRead(wrapper->data); 195 } 196 197 } // namespace android 198