MediaPuller.cpp revision a438123bd96c7faf145683876702387efe5628d9
1/* 2 * Copyright 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//#define LOG_NDEBUG 0 18#define LOG_TAG "MediaPuller" 19#include <utils/Log.h> 20 21#include "MediaPuller.h" 22 23#include <media/stagefright/foundation/ABuffer.h> 24#include <media/stagefright/foundation/ADebug.h> 25#include <media/stagefright/foundation/AMessage.h> 26#include <media/stagefright/MediaBuffer.h> 27#include <media/stagefright/MediaSource.h> 28#include <media/stagefright/MetaData.h> 29 30namespace android { 31 32MediaPuller::MediaPuller( 33 const sp<MediaSource> &source, const sp<AMessage> ¬ify) 34 : mSource(source), 35 mNotify(notify), 36 mPullGeneration(0), 37 mIsAudio(false) { 38 sp<MetaData> meta = source->getFormat(); 39 const char *mime; 40 CHECK(meta->findCString(kKeyMIMEType, &mime)); 41 42 mIsAudio = !strncasecmp(mime, "audio/", 6); 43} 44 45MediaPuller::~MediaPuller() { 46} 47 48status_t MediaPuller::postSynchronouslyAndReturnError( 49 const sp<AMessage> &msg) { 50 sp<AMessage> response; 51 status_t err = msg->postAndAwaitResponse(&response); 52 53 if (err != OK) { 54 return err; 55 } 56 57 if (!response->findInt32("err", &err)) { 58 err = OK; 59 } 60 61 return err; 62} 63 64status_t MediaPuller::start() { 65 return postSynchronouslyAndReturnError(new AMessage(kWhatStart, id())); 66} 67 68status_t MediaPuller::stop() { 69 return postSynchronouslyAndReturnError(new AMessage(kWhatStop, id())); 70} 71 72void MediaPuller::onMessageReceived(const sp<AMessage> &msg) { 73 switch (msg->what()) { 74 case kWhatStart: 75 case kWhatStop: 76 { 77 status_t err; 78 79 if (msg->what() == kWhatStart) { 80 err = mSource->start(); 81 82 if (err == OK) { 83 schedulePull(); 84 } 85 } else { 86 sp<MetaData> meta = mSource->getFormat(); 87 const char *tmp; 88 CHECK(meta->findCString(kKeyMIMEType, &tmp)); 89 AString mime = tmp; 90 91 ALOGI("MediaPuller(%s) stopping.", mime.c_str()); 92 err = mSource->stop(); 93 ALOGI("MediaPuller(%s) stopped.", mime.c_str()); 94 ++mPullGeneration; 95 } 96 97 sp<AMessage> response = new AMessage; 98 response->setInt32("err", err); 99 100 uint32_t replyID; 101 CHECK(msg->senderAwaitsResponse(&replyID)); 102 103 response->postReply(replyID); 104 break; 105 } 106 107 case kWhatPull: 108 { 109 int32_t generation; 110 CHECK(msg->findInt32("generation", &generation)); 111 112 if (generation != mPullGeneration) { 113 break; 114 } 115 116 MediaBuffer *mbuf; 117 status_t err = mSource->read(&mbuf); 118 119 if (err != OK) { 120 if (err == ERROR_END_OF_STREAM) { 121 ALOGI("stream ended."); 122 } else { 123 ALOGE("error %d reading stream.", err); 124 } 125 126 sp<AMessage> notify = mNotify->dup(); 127 notify->setInt32("what", kWhatEOS); 128 notify->post(); 129 } else { 130 int64_t timeUs; 131 CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs)); 132 133 sp<ABuffer> accessUnit = new ABuffer(mbuf->range_length()); 134 135 memcpy(accessUnit->data(), 136 (const uint8_t *)mbuf->data() + mbuf->range_offset(), 137 mbuf->range_length()); 138 139 accessUnit->meta()->setInt64("timeUs", timeUs); 140 141 if (mIsAudio) { 142 mbuf->release(); 143 mbuf = NULL; 144 } else { 145 // video encoder will release MediaBuffer when done 146 // with underlying data. 147 accessUnit->meta()->setPointer("mediaBuffer", mbuf); 148 } 149 150 sp<AMessage> notify = mNotify->dup(); 151 152 notify->setInt32("what", kWhatAccessUnit); 153 notify->setBuffer("accessUnit", accessUnit); 154 notify->post(); 155 156 schedulePull(); 157 } 158 break; 159 } 160 161 default: 162 TRESPASS(); 163 } 164} 165 166void MediaPuller::schedulePull() { 167 sp<AMessage> msg = new AMessage(kWhatPull, id()); 168 msg->setInt32("generation", mPullGeneration); 169 msg->post(); 170} 171 172} // namespace android 173 174