Converter.cpp revision dca352880e210e0ca0ff39de074540d3640ecfab
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 "Converter" 19#include <utils/Log.h> 20 21#include "Converter.h" 22 23#include <cutils/properties.h> 24#include <gui/SurfaceTextureClient.h> 25#include <media/ICrypto.h> 26#include <media/stagefright/foundation/ABuffer.h> 27#include <media/stagefright/foundation/ADebug.h> 28#include <media/stagefright/foundation/AMessage.h> 29#include <media/stagefright/MediaCodec.h> 30#include <media/stagefright/MediaDefs.h> 31#include <media/stagefright/MediaErrors.h> 32 33namespace android { 34 35Converter::Converter( 36 const sp<AMessage> ¬ify, 37 const sp<ALooper> &codecLooper, 38 const sp<AMessage> &format) 39 : mInitCheck(NO_INIT), 40 mNotify(notify), 41 mCodecLooper(codecLooper), 42 mInputFormat(format), 43 mDoMoreWorkPending(false) { 44 mInitCheck = initEncoder(); 45} 46 47Converter::~Converter() { 48 if (mEncoder != NULL) { 49 mEncoder->release(); 50 mEncoder.clear(); 51 } 52 53 AString mime; 54 CHECK(mInputFormat->findString("mime", &mime)); 55 ALOGI("encoder (%s) shut down.", mime.c_str()); 56} 57 58status_t Converter::initCheck() const { 59 return mInitCheck; 60} 61 62size_t Converter::getInputBufferCount() const { 63 return mEncoderInputBuffers.size(); 64} 65 66sp<AMessage> Converter::getOutputFormat() const { 67 return mOutputFormat; 68} 69 70static int32_t getBitrate(const char *propName, int32_t defaultValue) { 71 char val[PROPERTY_VALUE_MAX]; 72 if (property_get(propName, val, NULL)) { 73 char *end; 74 unsigned long x = strtoul(val, &end, 10); 75 76 if (*end == '\0' && end > val && x > 0) { 77 return x; 78 } 79 } 80 81 return defaultValue; 82} 83 84status_t Converter::initEncoder() { 85 AString inputMIME; 86 CHECK(mInputFormat->findString("mime", &inputMIME)); 87 88 AString outputMIME; 89 bool isAudio = false; 90 if (!strcasecmp(inputMIME.c_str(), MEDIA_MIMETYPE_AUDIO_RAW)) { 91 outputMIME = MEDIA_MIMETYPE_AUDIO_AAC; 92 isAudio = true; 93 } else if (!strcasecmp(inputMIME.c_str(), MEDIA_MIMETYPE_VIDEO_RAW)) { 94 outputMIME = MEDIA_MIMETYPE_VIDEO_AVC; 95 } else { 96 TRESPASS(); 97 } 98 99 mEncoder = MediaCodec::CreateByType( 100 mCodecLooper, outputMIME.c_str(), true /* encoder */); 101 102 if (mEncoder == NULL) { 103 return ERROR_UNSUPPORTED; 104 } 105 106 mOutputFormat = mInputFormat->dup(); 107 mOutputFormat->setString("mime", outputMIME.c_str()); 108 109 int32_t audioBitrate = getBitrate("media.wfd.audio-bitrate", 64000); 110 int32_t videoBitrate = getBitrate("media.wfd.video-bitrate", 10000000); 111 112 ALOGI("using audio bitrate of %d bps, video bitrate of %d bps", 113 audioBitrate, videoBitrate); 114 115 if (isAudio) { 116 mOutputFormat->setInt32("bitrate", audioBitrate); 117 } else { 118 mOutputFormat->setInt32("bitrate", videoBitrate); 119 mOutputFormat->setInt32("frame-rate", 30); 120 mOutputFormat->setInt32("i-frame-interval", 3); // Iframes every 3 secs 121 } 122 123 ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str()); 124 125 status_t err = mEncoder->configure( 126 mOutputFormat, 127 NULL /* nativeWindow */, 128 NULL /* crypto */, 129 MediaCodec::CONFIGURE_FLAG_ENCODE); 130 131 if (err != OK) { 132 return err; 133 } 134 135 err = mEncoder->start(); 136 137 if (err != OK) { 138 return err; 139 } 140 141 err = mEncoder->getInputBuffers(&mEncoderInputBuffers); 142 143 if (err != OK) { 144 return err; 145 } 146 147 return mEncoder->getOutputBuffers(&mEncoderOutputBuffers); 148} 149 150void Converter::feedAccessUnit(const sp<ABuffer> &accessUnit) { 151 sp<AMessage> msg = new AMessage(kWhatFeedAccessUnit, id()); 152 msg->setBuffer("accessUnit", accessUnit); 153 msg->post(); 154} 155 156void Converter::signalEOS() { 157 (new AMessage(kWhatInputEOS, id()))->post(); 158} 159 160void Converter::notifyError(status_t err) { 161 sp<AMessage> notify = mNotify->dup(); 162 notify->setInt32("what", kWhatError); 163 notify->setInt32("err", err); 164 notify->post(); 165} 166 167void Converter::onMessageReceived(const sp<AMessage> &msg) { 168 switch (msg->what()) { 169 case kWhatFeedAccessUnit: 170 { 171 sp<ABuffer> accessUnit; 172 CHECK(msg->findBuffer("accessUnit", &accessUnit)); 173 174 mInputBufferQueue.push_back(accessUnit); 175 176 feedEncoderInputBuffers(); 177 178 scheduleDoMoreWork(); 179 break; 180 } 181 182 case kWhatInputEOS: 183 { 184 mInputBufferQueue.push_back(NULL); 185 186 feedEncoderInputBuffers(); 187 188 scheduleDoMoreWork(); 189 break; 190 } 191 192 case kWhatDoMoreWork: 193 { 194 mDoMoreWorkPending = false; 195 status_t err = doMoreWork(); 196 197 if (err != OK) { 198 notifyError(err); 199 } else { 200 scheduleDoMoreWork(); 201 } 202 break; 203 } 204 205 default: 206 TRESPASS(); 207 } 208} 209 210void Converter::scheduleDoMoreWork() { 211 if (mDoMoreWorkPending) { 212 return; 213 } 214 215 mDoMoreWorkPending = true; 216 (new AMessage(kWhatDoMoreWork, id()))->post(1000ll); 217} 218 219status_t Converter::feedEncoderInputBuffers() { 220 while (!mInputBufferQueue.empty() 221 && !mAvailEncoderInputIndices.empty()) { 222 sp<ABuffer> buffer = *mInputBufferQueue.begin(); 223 mInputBufferQueue.erase(mInputBufferQueue.begin()); 224 225 size_t bufferIndex = *mAvailEncoderInputIndices.begin(); 226 mAvailEncoderInputIndices.erase(mAvailEncoderInputIndices.begin()); 227 228 int64_t timeUs = 0ll; 229 uint32_t flags = 0; 230 231 if (buffer != NULL) { 232 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 233 234 memcpy(mEncoderInputBuffers.itemAt(bufferIndex)->data(), 235 buffer->data(), 236 buffer->size()); 237 238 void *mediaBuffer; 239 if (buffer->meta()->findPointer("mediaBuffer", &mediaBuffer) 240 && mediaBuffer != NULL) { 241 mEncoderInputBuffers.itemAt(bufferIndex)->meta() 242 ->setPointer("mediaBuffer", mediaBuffer); 243 244 buffer->meta()->setPointer("mediaBuffer", NULL); 245 } 246 } else { 247 flags = MediaCodec::BUFFER_FLAG_EOS; 248 } 249 250 status_t err = mEncoder->queueInputBuffer( 251 bufferIndex, 0, (buffer == NULL) ? 0 : buffer->size(), 252 timeUs, flags); 253 254 if (err != OK) { 255 return err; 256 } 257 } 258 259 return OK; 260} 261 262status_t Converter::doMoreWork() { 263 size_t bufferIndex; 264 status_t err = mEncoder->dequeueInputBuffer(&bufferIndex); 265 266 if (err == OK) { 267 mAvailEncoderInputIndices.push_back(bufferIndex); 268 feedEncoderInputBuffers(); 269 } 270 271 size_t offset; 272 size_t size; 273 int64_t timeUs; 274 uint32_t flags; 275 err = mEncoder->dequeueOutputBuffer( 276 &bufferIndex, &offset, &size, &timeUs, &flags); 277 278 if (err == OK) { 279 if (flags & MediaCodec::BUFFER_FLAG_EOS) { 280 sp<AMessage> notify = mNotify->dup(); 281 notify->setInt32("what", kWhatEOS); 282 notify->post(); 283 } else { 284 sp<ABuffer> buffer = new ABuffer(size); 285 buffer->meta()->setInt64("timeUs", timeUs); 286 287 memcpy(buffer->data(), 288 mEncoderOutputBuffers.itemAt(bufferIndex)->base() + offset, 289 size); 290 291 if (flags & MediaCodec::BUFFER_FLAG_CODECCONFIG) { 292 mOutputFormat->setBuffer("csd-0", buffer); 293 } else { 294 sp<AMessage> notify = mNotify->dup(); 295 notify->setInt32("what", kWhatAccessUnit); 296 notify->setBuffer("accessUnit", buffer); 297 notify->post(); 298 } 299 } 300 301 err = mEncoder->releaseOutputBuffer(bufferIndex); 302 } else if (err == -EAGAIN) { 303 err = OK; 304 } 305 306 return err; 307} 308 309} // namespace android 310 311