StagefrightRecorder.cpp revision 13aec890216948b0c364f8f92792129d0335f506
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//#define LOG_NDEBUG 0 18#define LOG_TAG "StagefrightRecorder" 19#include <utils/Log.h> 20 21#include "StagefrightRecorder.h" 22 23#include <binder/IPCThreadState.h> 24#include <media/stagefright/AudioSource.h> 25#include <media/stagefright/AMRWriter.h> 26#include <media/stagefright/CameraSource.h> 27#include <media/stagefright/MPEG4Writer.h> 28#include <media/stagefright/MediaDebug.h> 29#include <media/stagefright/MediaDefs.h> 30#include <media/stagefright/MetaData.h> 31#include <media/stagefright/OMXClient.h> 32#include <media/stagefright/OMXCodec.h> 33#include <camera/ICamera.h> 34#include <camera/Camera.h> 35#include <surfaceflinger/ISurface.h> 36#include <utils/Errors.h> 37#include <sys/types.h> 38#include <unistd.h> 39#include <ctype.h> 40 41namespace android { 42 43StagefrightRecorder::StagefrightRecorder() { 44 reset(); 45} 46 47StagefrightRecorder::~StagefrightRecorder() { 48 stop(); 49 50 if (mOutputFd >= 0) { 51 ::close(mOutputFd); 52 mOutputFd = -1; 53 } 54} 55 56status_t StagefrightRecorder::init() { 57 return OK; 58} 59 60status_t StagefrightRecorder::setAudioSource(audio_source as) { 61 mAudioSource = as; 62 63 return OK; 64} 65 66status_t StagefrightRecorder::setVideoSource(video_source vs) { 67 mVideoSource = vs; 68 69 return OK; 70} 71 72status_t StagefrightRecorder::setOutputFormat(output_format of) { 73 mOutputFormat = of; 74 75 return OK; 76} 77 78status_t StagefrightRecorder::setAudioEncoder(audio_encoder ae) { 79 mAudioEncoder = ae; 80 81 return OK; 82} 83 84status_t StagefrightRecorder::setVideoEncoder(video_encoder ve) { 85 mVideoEncoder = ve; 86 87 return OK; 88} 89 90status_t StagefrightRecorder::setVideoSize(int width, int height) { 91 mVideoWidth = width; 92 mVideoHeight = height; 93 94 return OK; 95} 96 97status_t StagefrightRecorder::setVideoFrameRate(int frames_per_second) { 98 mFrameRate = frames_per_second; 99 100 return OK; 101} 102 103status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) { 104 LOGV("setCamera: pid %d pid %d", IPCThreadState::self()->getCallingPid(), getpid()); 105 if (camera == 0) { 106 LOGE("camera is NULL"); 107 return UNKNOWN_ERROR; 108 } 109 110 mFlags &= ~ FLAGS_SET_CAMERA | FLAGS_HOT_CAMERA; 111 mCamera = Camera::create(camera); 112 if (mCamera == 0) { 113 LOGE("Unable to connect to camera"); 114 return UNKNOWN_ERROR; 115 } 116 117 LOGV("Connected to camera"); 118 mFlags |= FLAGS_SET_CAMERA; 119 if (mCamera->previewEnabled()) { 120 LOGV("camera is hot"); 121 mFlags |= FLAGS_HOT_CAMERA; 122 } 123 124 return OK; 125} 126 127status_t StagefrightRecorder::setPreviewSurface(const sp<ISurface> &surface) { 128 mPreviewSurface = surface; 129 130 return OK; 131} 132 133status_t StagefrightRecorder::setOutputFile(const char *path) { 134 // We don't actually support this at all, as the media_server process 135 // no longer has permissions to create files. 136 137 return UNKNOWN_ERROR; 138} 139 140status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t length) { 141 // These don't make any sense, do they? 142 CHECK_EQ(offset, 0); 143 CHECK_EQ(length, 0); 144 145 if (mOutputFd >= 0) { 146 ::close(mOutputFd); 147 } 148 mOutputFd = dup(fd); 149 150 return OK; 151} 152 153// Attempt to parse an int64 literal optionally surrounded by whitespace, 154// returns true on success, false otherwise. 155static bool safe_strtoi64(const char *s, int32_t *val) { 156 char *end; 157 *val = static_cast<int32_t>(strtoll(s, &end, 10)); 158 159 if (end == s || errno == ERANGE) { 160 return false; 161 } 162 163 // Skip trailing whitespace 164 while (isspace(*end)) { 165 ++end; 166 } 167 168 // For a successful return, the string must contain nothing but a valid 169 // int64 literal optionally surrounded by whitespace. 170 171 return *end == '\0'; 172} 173 174// Trim both leading and trailing whitespace from the given string. 175static void TrimString(String8 *s) { 176 size_t num_bytes = s->bytes(); 177 const char *data = s->string(); 178 179 size_t leading_space = 0; 180 while (leading_space < num_bytes && isspace(data[leading_space])) { 181 ++leading_space; 182 } 183 184 size_t i = num_bytes; 185 while (i > leading_space && isspace(data[i - 1])) { 186 --i; 187 } 188 189 s->setTo(String8(&data[leading_space], i - leading_space)); 190} 191 192status_t StagefrightRecorder::setParamAudioSamplingRate(int32_t sampleRate) { 193 LOGV("setParamAudioSamplingRate: %d", sampleRate); 194 mSampleRate = sampleRate; 195 return OK; 196} 197 198status_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) { 199 LOGV("setParamAudioNumberOfChannels: %d", channels); 200 mAudioChannels = channels; 201 return OK; 202} 203 204status_t StagefrightRecorder::setParamAudioEncodingBitRate(int32_t bitRate) { 205 LOGV("setParamAudioEncodingBitRate: %d", bitRate); 206 mAudioBitRate = bitRate; 207 return OK; 208} 209 210status_t StagefrightRecorder::setParamVideoEncodingBitRate(int32_t bitRate) { 211 LOGV("setParamVideoEncodingBitRate: %d", bitRate); 212 mVideoBitRate = bitRate; 213 return OK; 214} 215 216status_t StagefrightRecorder::setParamMaxDurationOrFileSize(int32_t limit, 217 bool limit_is_duration) { 218 LOGV("setParamMaxDurationOrFileSize: limit (%d) for %s", 219 limit, limit_is_duration?"duration":"size"); 220 return OK; 221} 222 223status_t StagefrightRecorder::setParamInterleaveDuration(int32_t durationUs) { 224 LOGV("setParamInterleaveDuration: %d", durationUs); 225 mInterleaveDurationUs = durationUs; 226 return OK; 227} 228status_t StagefrightRecorder::setParameter( 229 const String8 &key, const String8 &value) { 230 LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string()); 231 if (key == "max-duration") { 232 int32_t max_duration_ms; 233 if (safe_strtoi64(value.string(), &max_duration_ms)) { 234 return setParamMaxDurationOrFileSize( 235 max_duration_ms, true /* limit_is_duration */); 236 } 237 } else if (key == "max-filesize") { 238 int32_t max_filesize_bytes; 239 if (safe_strtoi64(value.string(), &max_filesize_bytes)) { 240 return setParamMaxDurationOrFileSize( 241 max_filesize_bytes, false /* limit is filesize */); 242 } 243 } else if (key == "audio-param-sampling-rate") { 244 int32_t sampling_rate; 245 if (safe_strtoi64(value.string(), &sampling_rate)) { 246 return setParamAudioSamplingRate(sampling_rate); 247 } 248 } else if (key == "audio-param-number-of-channels") { 249 int32_t number_of_channels; 250 if (safe_strtoi64(value.string(), &number_of_channels)) { 251 return setParamAudioNumberOfChannels(number_of_channels); 252 } 253 } else if (key == "audio-param-encoding-bitrate") { 254 int32_t audio_bitrate; 255 if (safe_strtoi64(value.string(), &audio_bitrate)) { 256 return setParamAudioEncodingBitRate(audio_bitrate); 257 } 258 } else if (key == "video-param-encoding-bitrate") { 259 int32_t video_bitrate; 260 if (safe_strtoi64(value.string(), &video_bitrate)) { 261 return setParamVideoEncodingBitRate(video_bitrate); 262 } 263 } else if (key == "param-interleave-duration-us") { 264 int32_t durationUs; 265 if (safe_strtoi64(value.string(), &durationUs)) { 266 return setParamInterleaveDuration(durationUs); 267 } 268 } else { 269 LOGE("setParameter: failed to find key %s", key.string()); 270 return BAD_VALUE; 271 } 272 return OK; 273} 274 275status_t StagefrightRecorder::setParameters(const String8 ¶ms) { 276 LOGV("setParameters: %s", params.string()); 277 const char *cparams = params.string(); 278 const char *key_start = cparams; 279 for (;;) { 280 const char *equal_pos = strchr(key_start, '='); 281 if (equal_pos == NULL) { 282 LOGE("Parameters %s miss a value", cparams); 283 return BAD_VALUE; 284 } 285 String8 key(key_start, equal_pos - key_start); 286 TrimString(&key); 287 if (key.length() == 0) { 288 LOGE("Parameters %s contains an empty key", cparams); 289 return BAD_VALUE; 290 } 291 const char *value_start = equal_pos + 1; 292 const char *semicolon_pos = strchr(value_start, ';'); 293 String8 value; 294 if (semicolon_pos == NULL) { 295 value.setTo(value_start); 296 } else { 297 value.setTo(value_start, semicolon_pos - value_start); 298 } 299 if (setParameter(key, value) != OK) { 300 return BAD_VALUE; 301 } 302 if (semicolon_pos == NULL) { 303 break; // Reaches the end 304 } 305 key_start = semicolon_pos + 1; 306 } 307 return OK; 308} 309 310status_t StagefrightRecorder::setListener(const sp<IMediaPlayerClient> &listener) { 311 mListener = listener; 312 313 return OK; 314} 315 316status_t StagefrightRecorder::prepare() { 317 return OK; 318} 319 320status_t StagefrightRecorder::start() { 321 if (mWriter != NULL) { 322 return UNKNOWN_ERROR; 323 } 324 325 switch (mOutputFormat) { 326 case OUTPUT_FORMAT_DEFAULT: 327 case OUTPUT_FORMAT_THREE_GPP: 328 case OUTPUT_FORMAT_MPEG_4: 329 return startMPEG4Recording(); 330 331 case OUTPUT_FORMAT_AMR_NB: 332 case OUTPUT_FORMAT_AMR_WB: 333 return startAMRRecording(); 334 335 default: 336 return UNKNOWN_ERROR; 337 } 338} 339 340sp<MediaSource> StagefrightRecorder::createAudioSource() { 341 sp<AudioSource> audioSource = 342 new AudioSource( 343 mAudioSource, 344 mSampleRate, 345 AudioSystem::CHANNEL_IN_MONO); 346 347 status_t err = audioSource->initCheck(); 348 349 if (err != OK) { 350 LOGE("audio source is not initialized"); 351 return NULL; 352 } 353 354 sp<MetaData> encMeta = new MetaData; 355 const char *mime; 356 switch (mAudioEncoder) { 357 case AUDIO_ENCODER_AMR_NB: 358 case AUDIO_ENCODER_DEFAULT: 359 mime = MEDIA_MIMETYPE_AUDIO_AMR_NB; 360 break; 361 case AUDIO_ENCODER_AMR_WB: 362 mime = MEDIA_MIMETYPE_AUDIO_AMR_WB; 363 break; 364 case AUDIO_ENCODER_AAC: 365 mime = MEDIA_MIMETYPE_AUDIO_AAC; 366 break; 367 default: 368 LOGE("Unknown audio encoder: %d", mAudioEncoder); 369 return NULL; 370 } 371 encMeta->setCString(kKeyMIMEType, mime); 372 373 int32_t maxInputSize; 374 CHECK(audioSource->getFormat()->findInt32( 375 kKeyMaxInputSize, &maxInputSize)); 376 377 encMeta->setInt32(kKeyMaxInputSize, maxInputSize); 378 encMeta->setInt32(kKeyChannelCount, mAudioChannels); 379 encMeta->setInt32(kKeySampleRate, mSampleRate); 380 381 OMXClient client; 382 CHECK_EQ(client.connect(), OK); 383 384 sp<MediaSource> audioEncoder = 385 OMXCodec::Create(client.interface(), encMeta, 386 true /* createEncoder */, audioSource); 387 388 return audioEncoder; 389} 390 391status_t StagefrightRecorder::startAMRRecording() { 392 if (mAudioSource == AUDIO_SOURCE_LIST_END 393 || mVideoSource != VIDEO_SOURCE_LIST_END) { 394 return UNKNOWN_ERROR; 395 } 396 397 if (mOutputFormat == OUTPUT_FORMAT_AMR_NB 398 && mAudioEncoder != AUDIO_ENCODER_DEFAULT 399 && mAudioEncoder != AUDIO_ENCODER_AMR_NB) { 400 return UNKNOWN_ERROR; 401 } else if (mOutputFormat == OUTPUT_FORMAT_AMR_WB 402 && mAudioEncoder != AUDIO_ENCODER_AMR_WB) { 403 return UNKNOWN_ERROR; 404 } 405 406 sp<MediaSource> audioEncoder = createAudioSource(); 407 408 if (audioEncoder == NULL) { 409 return UNKNOWN_ERROR; 410 } 411 412 CHECK(mOutputFd >= 0); 413 mWriter = new AMRWriter(dup(mOutputFd)); 414 mWriter->addSource(audioEncoder); 415 mWriter->start(); 416 417 return OK; 418} 419 420status_t StagefrightRecorder::startMPEG4Recording() { 421 mWriter = new MPEG4Writer(dup(mOutputFd)); 422 423 // Add audio source first if it exists 424 if (mAudioSource != AUDIO_SOURCE_LIST_END) { 425 sp<MediaSource> audioEncoder; 426 switch(mAudioEncoder) { 427 case AUDIO_ENCODER_AMR_NB: 428 case AUDIO_ENCODER_AMR_WB: 429 case AUDIO_ENCODER_AAC: 430 audioEncoder = createAudioSource(); 431 break; 432 default: 433 LOGE("Unsupported audio encoder: %d", mAudioEncoder); 434 return UNKNOWN_ERROR; 435 } 436 437 if (audioEncoder == NULL) { 438 return UNKNOWN_ERROR; 439 } 440 441 mWriter->addSource(audioEncoder); 442 } 443 if (mVideoSource == VIDEO_SOURCE_DEFAULT 444 || mVideoSource == VIDEO_SOURCE_CAMERA) { 445 CHECK(mCamera != NULL); 446 447 sp<CameraSource> cameraSource = 448 CameraSource::CreateFromCamera(mCamera); 449 450 CHECK(cameraSource != NULL); 451 452 cameraSource->setPreviewSurface(mPreviewSurface); 453 454 sp<MetaData> enc_meta = new MetaData; 455 switch (mVideoEncoder) { 456 case VIDEO_ENCODER_H263: 457 enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263); 458 break; 459 460 case VIDEO_ENCODER_MPEG_4_SP: 461 enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); 462 break; 463 464 case VIDEO_ENCODER_H264: 465 enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); 466 break; 467 468 default: 469 CHECK(!"Should not be here, unsupported video encoding."); 470 break; 471 } 472 473 sp<MetaData> meta = cameraSource->getFormat(); 474 475 int32_t width, height; 476 CHECK(meta->findInt32(kKeyWidth, &width)); 477 CHECK(meta->findInt32(kKeyHeight, &height)); 478 479 enc_meta->setInt32(kKeyWidth, width); 480 enc_meta->setInt32(kKeyHeight, height); 481 482 OMXClient client; 483 CHECK_EQ(client.connect(), OK); 484 485 sp<MediaSource> encoder = 486 OMXCodec::Create( 487 client.interface(), enc_meta, 488 true /* createEncoder */, cameraSource); 489 490 CHECK(mOutputFd >= 0); 491 mWriter->addSource(encoder); 492 } 493 494 ((MPEG4Writer *)mWriter.get())->setInterleaveDuration(mInterleaveDurationUs); 495 mWriter->start(); 496 return OK; 497} 498 499status_t StagefrightRecorder::stop() { 500 if (mWriter == NULL) { 501 return UNKNOWN_ERROR; 502 } 503 504 mWriter->stop(); 505 mWriter = NULL; 506 507 return OK; 508} 509 510status_t StagefrightRecorder::close() { 511 stop(); 512 513 if (mCamera != 0) { 514 if ((mFlags & FLAGS_HOT_CAMERA) == 0) { 515 LOGV("Camera was cold when we started, stopping preview"); 516 mCamera->stopPreview(); 517 } 518 if (mFlags & FLAGS_SET_CAMERA) { 519 LOGV("Unlocking camera"); 520 mCamera->unlock(); 521 } 522 mFlags = 0; 523 } 524 return OK; 525} 526 527status_t StagefrightRecorder::reset() { 528 stop(); 529 530 // No audio or video source by default 531 mAudioSource = AUDIO_SOURCE_LIST_END; 532 mVideoSource = VIDEO_SOURCE_LIST_END; 533 534 // Default parameters 535 mOutputFormat = OUTPUT_FORMAT_THREE_GPP; 536 mAudioEncoder = AUDIO_ENCODER_AMR_NB; 537 mVideoEncoder = VIDEO_ENCODER_H263; 538 mVideoWidth = 176; 539 mVideoHeight = 144; 540 mFrameRate = 20; 541 mVideoBitRate = 192000; 542 mSampleRate = 8000; 543 mAudioChannels = 1; 544 mAudioBitRate = 12200; 545 546 mOutputFd = -1; 547 mFlags = 0; 548 549 return OK; 550} 551 552status_t StagefrightRecorder::getMaxAmplitude(int *max) { 553 *max = 0; 554 555 return OK; 556} 557 558} // namespace android 559