StagefrightRecorder.cpp revision 93d6b102a13afa23bfa80d74c399d93d542e6ad6
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 <media/MediaProfiles.h> 34#include <camera/ICamera.h> 35#include <camera/Camera.h> 36#include <camera/CameraParameters.h> 37#include <surfaceflinger/ISurface.h> 38#include <utils/Errors.h> 39#include <sys/types.h> 40#include <unistd.h> 41#include <ctype.h> 42 43namespace android { 44 45StagefrightRecorder::StagefrightRecorder() { 46 reset(); 47} 48 49StagefrightRecorder::~StagefrightRecorder() { 50 stop(); 51 52 if (mOutputFd >= 0) { 53 ::close(mOutputFd); 54 mOutputFd = -1; 55 } 56} 57 58status_t StagefrightRecorder::init() { 59 return OK; 60} 61 62status_t StagefrightRecorder::setAudioSource(audio_source as) { 63 mAudioSource = as; 64 65 return OK; 66} 67 68status_t StagefrightRecorder::setVideoSource(video_source vs) { 69 mVideoSource = vs; 70 71 return OK; 72} 73 74status_t StagefrightRecorder::setOutputFormat(output_format of) { 75 mOutputFormat = of; 76 77 return OK; 78} 79 80status_t StagefrightRecorder::setAudioEncoder(audio_encoder ae) { 81 mAudioEncoder = ae; 82 83 return OK; 84} 85 86status_t StagefrightRecorder::setVideoEncoder(video_encoder ve) { 87 mVideoEncoder = ve; 88 89 return OK; 90} 91 92status_t StagefrightRecorder::setVideoSize(int width, int height) { 93 if (width <= 0 || height <= 0) { 94 LOGE("Invalid video size: %dx%d", width, height); 95 return BAD_VALUE; 96 } 97 98 // Additional check on the dimension will be performed later 99 mVideoWidth = width; 100 mVideoHeight = height; 101 102 return OK; 103} 104 105status_t StagefrightRecorder::setVideoFrameRate(int frames_per_second) { 106 if (frames_per_second <= 0 || frames_per_second > 30) { 107 LOGE("Invalid video frame rate: %d", frames_per_second); 108 return BAD_VALUE; 109 } 110 111 // Additional check on the frame rate will be performed later 112 mFrameRate = frames_per_second; 113 114 return OK; 115} 116 117status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) { 118 LOGV("setCamera"); 119 if (camera == 0) { 120 LOGE("camera is NULL"); 121 return UNKNOWN_ERROR; 122 } 123 124 int64_t token = IPCThreadState::self()->clearCallingIdentity(); 125 mFlags &= ~FLAGS_HOT_CAMERA; 126 mCamera = Camera::create(camera); 127 if (mCamera == 0) { 128 LOGE("Unable to connect to camera"); 129 IPCThreadState::self()->restoreCallingIdentity(token); 130 return UNKNOWN_ERROR; 131 } 132 133 LOGV("Connected to camera"); 134 if (mCamera->previewEnabled()) { 135 LOGV("camera is hot"); 136 mFlags |= FLAGS_HOT_CAMERA; 137 } 138 IPCThreadState::self()->restoreCallingIdentity(token); 139 140 return OK; 141} 142 143status_t StagefrightRecorder::setPreviewSurface(const sp<ISurface> &surface) { 144 mPreviewSurface = surface; 145 146 return OK; 147} 148 149status_t StagefrightRecorder::setOutputFile(const char *path) { 150 // We don't actually support this at all, as the media_server process 151 // no longer has permissions to create files. 152 153 return UNKNOWN_ERROR; 154} 155 156status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t length) { 157 // These don't make any sense, do they? 158 CHECK_EQ(offset, 0); 159 CHECK_EQ(length, 0); 160 161 if (mOutputFd >= 0) { 162 ::close(mOutputFd); 163 } 164 mOutputFd = dup(fd); 165 166 return OK; 167} 168 169// Attempt to parse an int64 literal optionally surrounded by whitespace, 170// returns true on success, false otherwise. 171static bool safe_strtoi64(const char *s, int64_t *val) { 172 char *end; 173 *val = strtoll(s, &end, 10); 174 175 if (end == s || errno == ERANGE) { 176 return false; 177 } 178 179 // Skip trailing whitespace 180 while (isspace(*end)) { 181 ++end; 182 } 183 184 // For a successful return, the string must contain nothing but a valid 185 // int64 literal optionally surrounded by whitespace. 186 187 return *end == '\0'; 188} 189 190// Return true if the value is in [0, 0x007FFFFFFF] 191static bool safe_strtoi32(const char *s, int32_t *val) { 192 int64_t temp; 193 if (safe_strtoi64(s, &temp)) { 194 if (temp >= 0 && temp <= 0x007FFFFFFF) { 195 *val = static_cast<int32_t>(temp); 196 return true; 197 } 198 } 199 return false; 200} 201 202// Trim both leading and trailing whitespace from the given string. 203static void TrimString(String8 *s) { 204 size_t num_bytes = s->bytes(); 205 const char *data = s->string(); 206 207 size_t leading_space = 0; 208 while (leading_space < num_bytes && isspace(data[leading_space])) { 209 ++leading_space; 210 } 211 212 size_t i = num_bytes; 213 while (i > leading_space && isspace(data[i - 1])) { 214 --i; 215 } 216 217 s->setTo(String8(&data[leading_space], i - leading_space)); 218} 219 220status_t StagefrightRecorder::setParamAudioSamplingRate(int32_t sampleRate) { 221 LOGV("setParamAudioSamplingRate: %d", sampleRate); 222 if (sampleRate <= 0) { 223 LOGE("Invalid audio sampling rate: %d", sampleRate); 224 return BAD_VALUE; 225 } 226 227 // Additional check on the sample rate will be performed later. 228 mSampleRate = sampleRate; 229 return OK; 230} 231 232status_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) { 233 LOGV("setParamAudioNumberOfChannels: %d", channels); 234 if (channels <= 0 || channels >= 3) { 235 LOGE("Invalid number of audio channels: %d", channels); 236 } 237 238 // Additional check on the number of channels will be performed later. 239 mAudioChannels = channels; 240 return OK; 241} 242 243status_t StagefrightRecorder::setParamAudioEncodingBitRate(int32_t bitRate) { 244 LOGV("setParamAudioEncodingBitRate: %d", bitRate); 245 if (bitRate <= 0) { 246 LOGE("Invalid audio encoding bit rate: %d", bitRate); 247 return BAD_VALUE; 248 } 249 250 // The target bit rate may not be exactly the same as the requested. 251 // It depends on many factors, such as rate control, and the bit rate 252 // range that a specific encoder supports. The mismatch between the 253 // the target and requested bit rate will NOT be treated as an error. 254 mAudioBitRate = bitRate; 255 return OK; 256} 257 258status_t StagefrightRecorder::setParamVideoEncodingBitRate(int32_t bitRate) { 259 LOGV("setParamVideoEncodingBitRate: %d", bitRate); 260 if (bitRate <= 0) { 261 LOGE("Invalid video encoding bit rate: %d", bitRate); 262 return BAD_VALUE; 263 } 264 265 // The target bit rate may not be exactly the same as the requested. 266 // It depends on many factors, such as rate control, and the bit rate 267 // range that a specific encoder supports. The mismatch between the 268 // the target and requested bit rate will NOT be treated as an error. 269 mVideoBitRate = bitRate; 270 return OK; 271} 272 273status_t StagefrightRecorder::setParamMaxDurationOrFileSize(int64_t limit, 274 bool limit_is_duration) { 275 LOGV("setParamMaxDurationOrFileSize: limit (%lld) for %s", 276 limit, limit_is_duration?"duration":"size"); 277 if (limit_is_duration) { // limit is in ms 278 if (limit <= 1000) { // XXX: 1 second 279 LOGE("Max file duration is too short: %lld us", limit); 280 } 281 mMaxFileDurationUs = limit * 1000LL; 282 } else { 283 if (limit <= 1024) { // XXX: 1 kB 284 LOGE("Max file size is too small: %lld bytes", limit); 285 } 286 mMaxFileSizeBytes = limit; 287 } 288 return OK; 289} 290 291status_t StagefrightRecorder::setParamInterleaveDuration(int32_t durationUs) { 292 LOGV("setParamInterleaveDuration: %d", durationUs); 293 if (durationUs <= 500000) { // 500 ms 294 // If interleave duration is too small, it is very inefficient to do 295 // interleaving since the metadata overhead will count for a significant 296 // portion of the saved contents 297 LOGE("Audio/video interleave duration is too small: %d us", durationUs); 298 return BAD_VALUE; 299 } else if (durationUs >= 10000000) { // 10 seconds 300 // If interleaving duration is too large, it can cause the recording 301 // session to use too much memory since we have to save the output 302 // data before we write them out 303 LOGE("Audio/video interleave duration is too large: %d us", durationUs); 304 return BAD_VALUE; 305 } 306 mInterleaveDurationUs = durationUs; 307 return OK; 308} 309 310// If interval < 0, only the first frame is I frame, and rest are all P frames 311// If interval == 0, all frames are encoded as I frames. No P frames 312// If interval > 0, it is the time spacing between 2 neighboring I frames 313status_t StagefrightRecorder::setParamVideoIFramesInterval(int32_t interval) { 314 LOGV("setParamVideoIFramesInterval: %d seconds", interval); 315 mIFramesInterval = interval; 316 return OK; 317} 318 319status_t StagefrightRecorder::setParam64BitFileOffset(bool use64Bit) { 320 LOGV("setParam64BitFileOffset: %s", 321 use64Bit? "use 64 bit file offset": "use 32 bit file offset"); 322 mUse64BitFileOffset = use64Bit; 323 return OK; 324} 325 326status_t StagefrightRecorder::setParamVideoCameraId(int32_t cameraId) { 327 LOGV("setParamVideoCameraId: %d", cameraId); 328 if (cameraId < 0) { 329 return BAD_VALUE; 330 } 331 mCameraId = cameraId; 332 return OK; 333} 334 335status_t StagefrightRecorder::setParamTrackFrameStatus(int32_t nFrames) { 336 LOGV("setParamTrackFrameStatus: %d", nFrames); 337 if (nFrames <= 0) { 338 return BAD_VALUE; 339 } 340 mTrackEveryNumberOfFrames = nFrames; 341 return OK; 342} 343 344status_t StagefrightRecorder::setParamTrackTimeStatus(int64_t timeDurationUs) { 345 LOGV("setParamTrackTimeStatus: %lld", timeDurationUs); 346 if (timeDurationUs < 20000) { // Infeasible if shorter than 20 ms? 347 return BAD_VALUE; 348 } 349 mTrackEveryTimeDurationUs = timeDurationUs; 350 return OK; 351} 352 353status_t StagefrightRecorder::setParameter( 354 const String8 &key, const String8 &value) { 355 LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string()); 356 if (key == "max-duration") { 357 int64_t max_duration_ms; 358 if (safe_strtoi64(value.string(), &max_duration_ms)) { 359 return setParamMaxDurationOrFileSize( 360 max_duration_ms, true /* limit_is_duration */); 361 } 362 } else if (key == "max-filesize") { 363 int64_t max_filesize_bytes; 364 if (safe_strtoi64(value.string(), &max_filesize_bytes)) { 365 return setParamMaxDurationOrFileSize( 366 max_filesize_bytes, false /* limit is filesize */); 367 } 368 } else if (key == "interleave-duration-us") { 369 int32_t durationUs; 370 if (safe_strtoi32(value.string(), &durationUs)) { 371 return setParamInterleaveDuration(durationUs); 372 } 373 } else if (key == "param-use-64bit-offset") { 374 int32_t use64BitOffset; 375 if (safe_strtoi32(value.string(), &use64BitOffset)) { 376 return setParam64BitFileOffset(use64BitOffset != 0); 377 } 378 } else if (key == "param-track-frame-status") { 379 int32_t nFrames; 380 if (safe_strtoi32(value.string(), &nFrames)) { 381 return setParamTrackFrameStatus(nFrames); 382 } 383 } else if (key == "param-track-time-status") { 384 int64_t timeDurationUs; 385 if (safe_strtoi64(value.string(), &timeDurationUs)) { 386 return setParamTrackTimeStatus(timeDurationUs); 387 } 388 } else if (key == "audio-param-sampling-rate") { 389 int32_t sampling_rate; 390 if (safe_strtoi32(value.string(), &sampling_rate)) { 391 return setParamAudioSamplingRate(sampling_rate); 392 } 393 } else if (key == "audio-param-number-of-channels") { 394 int32_t number_of_channels; 395 if (safe_strtoi32(value.string(), &number_of_channels)) { 396 return setParamAudioNumberOfChannels(number_of_channels); 397 } 398 } else if (key == "audio-param-encoding-bitrate") { 399 int32_t audio_bitrate; 400 if (safe_strtoi32(value.string(), &audio_bitrate)) { 401 return setParamAudioEncodingBitRate(audio_bitrate); 402 } 403 } else if (key == "video-param-encoding-bitrate") { 404 int32_t video_bitrate; 405 if (safe_strtoi32(value.string(), &video_bitrate)) { 406 return setParamVideoEncodingBitRate(video_bitrate); 407 } 408 } else if (key == "video-param-i-frames-interval") { 409 int32_t interval; 410 if (safe_strtoi32(value.string(), &interval)) { 411 return setParamVideoIFramesInterval(interval); 412 } 413 } else if (key == "video-param-camera-id") { 414 int32_t cameraId; 415 if (safe_strtoi32(value.string(), &cameraId)) { 416 return setParamVideoCameraId(cameraId); 417 } 418 } else { 419 LOGE("setParameter: failed to find key %s", key.string()); 420 } 421 return BAD_VALUE; 422} 423 424status_t StagefrightRecorder::setParameters(const String8 ¶ms) { 425 LOGV("setParameters: %s", params.string()); 426 const char *cparams = params.string(); 427 const char *key_start = cparams; 428 for (;;) { 429 const char *equal_pos = strchr(key_start, '='); 430 if (equal_pos == NULL) { 431 LOGE("Parameters %s miss a value", cparams); 432 return BAD_VALUE; 433 } 434 String8 key(key_start, equal_pos - key_start); 435 TrimString(&key); 436 if (key.length() == 0) { 437 LOGE("Parameters %s contains an empty key", cparams); 438 return BAD_VALUE; 439 } 440 const char *value_start = equal_pos + 1; 441 const char *semicolon_pos = strchr(value_start, ';'); 442 String8 value; 443 if (semicolon_pos == NULL) { 444 value.setTo(value_start); 445 } else { 446 value.setTo(value_start, semicolon_pos - value_start); 447 } 448 if (setParameter(key, value) != OK) { 449 return BAD_VALUE; 450 } 451 if (semicolon_pos == NULL) { 452 break; // Reaches the end 453 } 454 key_start = semicolon_pos + 1; 455 } 456 return OK; 457} 458 459status_t StagefrightRecorder::setListener(const sp<IMediaPlayerClient> &listener) { 460 mListener = listener; 461 462 return OK; 463} 464 465status_t StagefrightRecorder::prepare() { 466 return OK; 467} 468 469status_t StagefrightRecorder::start() { 470 if (mWriter != NULL) { 471 return UNKNOWN_ERROR; 472 } 473 474 switch (mOutputFormat) { 475 case OUTPUT_FORMAT_DEFAULT: 476 case OUTPUT_FORMAT_THREE_GPP: 477 case OUTPUT_FORMAT_MPEG_4: 478 return startMPEG4Recording(); 479 480 case OUTPUT_FORMAT_AMR_NB: 481 case OUTPUT_FORMAT_AMR_WB: 482 return startAMRRecording(); 483 484 case OUTPUT_FORMAT_AAC_ADIF: 485 case OUTPUT_FORMAT_AAC_ADTS: 486 return startAACRecording(); 487 488 default: 489 return UNKNOWN_ERROR; 490 } 491} 492 493sp<MediaSource> StagefrightRecorder::createAudioSource() { 494 sp<AudioSource> audioSource = 495 new AudioSource( 496 mAudioSource, 497 mSampleRate, 498 mAudioChannels); 499 500 status_t err = audioSource->initCheck(); 501 502 if (err != OK) { 503 LOGE("audio source is not initialized"); 504 return NULL; 505 } 506 507 sp<MetaData> encMeta = new MetaData; 508 const char *mime; 509 switch (mAudioEncoder) { 510 case AUDIO_ENCODER_AMR_NB: 511 case AUDIO_ENCODER_DEFAULT: 512 mime = MEDIA_MIMETYPE_AUDIO_AMR_NB; 513 break; 514 case AUDIO_ENCODER_AMR_WB: 515 mime = MEDIA_MIMETYPE_AUDIO_AMR_WB; 516 break; 517 case AUDIO_ENCODER_AAC: 518 mime = MEDIA_MIMETYPE_AUDIO_AAC; 519 break; 520 default: 521 LOGE("Unknown audio encoder: %d", mAudioEncoder); 522 return NULL; 523 } 524 encMeta->setCString(kKeyMIMEType, mime); 525 526 int32_t maxInputSize; 527 CHECK(audioSource->getFormat()->findInt32( 528 kKeyMaxInputSize, &maxInputSize)); 529 530 encMeta->setInt32(kKeyMaxInputSize, maxInputSize); 531 encMeta->setInt32(kKeyChannelCount, mAudioChannels); 532 encMeta->setInt32(kKeySampleRate, mSampleRate); 533 encMeta->setInt32(kKeyBitRate, mAudioBitRate); 534 535 OMXClient client; 536 CHECK_EQ(client.connect(), OK); 537 538 sp<MediaSource> audioEncoder = 539 OMXCodec::Create(client.interface(), encMeta, 540 true /* createEncoder */, audioSource); 541 mAudioSourceNode = audioSource; 542 543 return audioEncoder; 544} 545 546status_t StagefrightRecorder::startAACRecording() { 547 CHECK(mOutputFormat == OUTPUT_FORMAT_AAC_ADIF || 548 mOutputFormat == OUTPUT_FORMAT_AAC_ADTS); 549 550 CHECK(mAudioEncoder == AUDIO_ENCODER_AAC); 551 CHECK(mAudioSource != AUDIO_SOURCE_LIST_END); 552 CHECK(mOutputFd >= 0); 553 554 CHECK(0 == "AACWriter is not implemented yet"); 555 556 return OK; 557} 558 559status_t StagefrightRecorder::startAMRRecording() { 560 CHECK(mOutputFormat == OUTPUT_FORMAT_AMR_NB || 561 mOutputFormat == OUTPUT_FORMAT_AMR_WB); 562 563 if (mOutputFormat == OUTPUT_FORMAT_AMR_NB) { 564 if (mAudioEncoder != AUDIO_ENCODER_DEFAULT && 565 mAudioEncoder != AUDIO_ENCODER_AMR_NB) { 566 LOGE("Invalid encoder %d used for AMRNB recording", 567 mAudioEncoder); 568 return UNKNOWN_ERROR; 569 } 570 if (mSampleRate != 8000) { 571 LOGE("Invalid sampling rate %d used for AMRNB recording", 572 mSampleRate); 573 return UNKNOWN_ERROR; 574 } 575 } else { // mOutputFormat must be OUTPUT_FORMAT_AMR_WB 576 if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) { 577 LOGE("Invlaid encoder %d used for AMRWB recording", 578 mAudioEncoder); 579 return UNKNOWN_ERROR; 580 } 581 if (mSampleRate != 16000) { 582 LOGE("Invalid sample rate %d used for AMRWB recording", 583 mSampleRate); 584 return UNKNOWN_ERROR; 585 } 586 } 587 if (mAudioChannels != 1) { 588 LOGE("Invalid number of audio channels %d used for amr recording", 589 mAudioChannels); 590 return UNKNOWN_ERROR; 591 } 592 593 if (mAudioSource >= AUDIO_SOURCE_LIST_END) { 594 LOGE("Invalid audio source: %d", mAudioSource); 595 return UNKNOWN_ERROR; 596 } 597 598 sp<MediaSource> audioEncoder = createAudioSource(); 599 600 if (audioEncoder == NULL) { 601 return UNKNOWN_ERROR; 602 } 603 604 CHECK(mOutputFd >= 0); 605 mWriter = new AMRWriter(dup(mOutputFd)); 606 mWriter->addSource(audioEncoder); 607 608 if (mMaxFileDurationUs != 0) { 609 mWriter->setMaxFileDuration(mMaxFileDurationUs); 610 } 611 if (mMaxFileSizeBytes != 0) { 612 mWriter->setMaxFileSize(mMaxFileSizeBytes); 613 } 614 mWriter->setListener(mListener); 615 mWriter->start(); 616 617 return OK; 618} 619 620void StagefrightRecorder::clipVideoFrameRate() { 621 LOGV("clipVideoFrameRate: encoder %d", mVideoEncoder); 622 int minFrameRate = mEncoderProfiles->getVideoEncoderParamByName( 623 "enc.vid.fps.min", mVideoEncoder); 624 int maxFrameRate = mEncoderProfiles->getVideoEncoderParamByName( 625 "enc.vid.fps.max", mVideoEncoder); 626 if (mFrameRate < minFrameRate) { 627 LOGW("Intended video encoding frame rate (%d fps) is too small" 628 " and will be set to (%d fps)", mFrameRate, minFrameRate); 629 mFrameRate = minFrameRate; 630 } else if (mFrameRate > maxFrameRate) { 631 LOGW("Intended video encoding frame rate (%d fps) is too large" 632 " and will be set to (%d fps)", mFrameRate, maxFrameRate); 633 mFrameRate = maxFrameRate; 634 } 635} 636 637void StagefrightRecorder::clipVideoBitRate() { 638 LOGV("clipVideoBitRate: encoder %d", mVideoEncoder); 639 int minBitRate = mEncoderProfiles->getVideoEncoderParamByName( 640 "enc.vid.bps.min", mVideoEncoder); 641 int maxBitRate = mEncoderProfiles->getVideoEncoderParamByName( 642 "enc.vid.bps.max", mVideoEncoder); 643 if (mVideoBitRate < minBitRate) { 644 LOGW("Intended video encoding bit rate (%d bps) is too small" 645 " and will be set to (%d bps)", mVideoBitRate, minBitRate); 646 mVideoBitRate = minBitRate; 647 } else if (mVideoBitRate > maxBitRate) { 648 LOGW("Intended video encoding bit rate (%d bps) is too large" 649 " and will be set to (%d bps)", mVideoBitRate, maxBitRate); 650 mVideoBitRate = maxBitRate; 651 } 652} 653 654void StagefrightRecorder::clipVideoFrameWidth() { 655 LOGV("clipVideoFrameWidth: encoder %d", mVideoEncoder); 656 int minFrameWidth = mEncoderProfiles->getVideoEncoderParamByName( 657 "enc.vid.width.min", mVideoEncoder); 658 int maxFrameWidth = mEncoderProfiles->getVideoEncoderParamByName( 659 "enc.vid.width.max", mVideoEncoder); 660 if (mVideoWidth < minFrameWidth) { 661 LOGW("Intended video encoding frame width (%d) is too small" 662 " and will be set to (%d)", mVideoWidth, minFrameWidth); 663 mVideoWidth = minFrameWidth; 664 } else if (mVideoWidth > maxFrameWidth) { 665 LOGW("Intended video encoding frame width (%d) is too large" 666 " and will be set to (%d)", mVideoWidth, maxFrameWidth); 667 mVideoWidth = maxFrameWidth; 668 } 669} 670 671void StagefrightRecorder::clipVideoFrameHeight() { 672 LOGV("clipVideoFrameHeight: encoder %d", mVideoEncoder); 673 int minFrameHeight = mEncoderProfiles->getVideoEncoderParamByName( 674 "enc.vid.height.min", mVideoEncoder); 675 int maxFrameHeight = mEncoderProfiles->getVideoEncoderParamByName( 676 "enc.vid.height.max", mVideoEncoder); 677 if (mVideoHeight < minFrameHeight) { 678 LOGW("Intended video encoding frame height (%d) is too small" 679 " and will be set to (%d)", mVideoHeight, minFrameHeight); 680 mVideoHeight = minFrameHeight; 681 } else if (mVideoHeight > maxFrameHeight) { 682 LOGW("Intended video encoding frame height (%d) is too large" 683 " and will be set to (%d)", mVideoHeight, maxFrameHeight); 684 mVideoHeight = maxFrameHeight; 685 } 686} 687 688status_t StagefrightRecorder::startMPEG4Recording() { 689 mWriter = new MPEG4Writer(dup(mOutputFd)); 690 int32_t totalBitRate = 0; 691 692 // Add audio source first if it exists 693 if (mAudioSource != AUDIO_SOURCE_LIST_END) { 694 sp<MediaSource> audioEncoder; 695 switch(mAudioEncoder) { 696 case AUDIO_ENCODER_AMR_NB: 697 case AUDIO_ENCODER_AMR_WB: 698 case AUDIO_ENCODER_AAC: 699 audioEncoder = createAudioSource(); 700 break; 701 default: 702 LOGE("Unsupported audio encoder: %d", mAudioEncoder); 703 return UNKNOWN_ERROR; 704 } 705 706 if (audioEncoder == NULL) { 707 return UNKNOWN_ERROR; 708 } 709 totalBitRate += mAudioBitRate; 710 mWriter->addSource(audioEncoder); 711 } 712 if (mVideoSource == VIDEO_SOURCE_DEFAULT 713 || mVideoSource == VIDEO_SOURCE_CAMERA) { 714 715 clipVideoBitRate(); 716 clipVideoFrameRate(); 717 clipVideoFrameWidth(); 718 clipVideoFrameHeight(); 719 720 int64_t token = IPCThreadState::self()->clearCallingIdentity(); 721 if (mCamera == 0) { 722 mCamera = Camera::connect(mCameraId); 723 mCamera->lock(); 724 } 725 726 // Set the actual video recording frame size 727 CameraParameters params(mCamera->getParameters()); 728 params.setPreviewSize(mVideoWidth, mVideoHeight); 729 params.setPreviewFrameRate(mFrameRate); 730 String8 s = params.flatten(); 731 CHECK_EQ(OK, mCamera->setParameters(s)); 732 CameraParameters newCameraParams(mCamera->getParameters()); 733 734 // Check on video frame size 735 int frameWidth = 0, frameHeight = 0; 736 newCameraParams.getPreviewSize(&frameWidth, &frameHeight); 737 if (frameWidth < 0 || frameWidth != mVideoWidth || 738 frameHeight < 0 || frameHeight != mVideoHeight) { 739 LOGE("Failed to set the video frame size to %dx%d", 740 mVideoWidth, mVideoHeight); 741 IPCThreadState::self()->restoreCallingIdentity(token); 742 return UNKNOWN_ERROR; 743 } 744 745 // Check on video frame rate 746 int frameRate = newCameraParams.getPreviewFrameRate(); 747 if (frameRate < 0 || (frameRate - mFrameRate) != 0) { 748 LOGE("Failed to set frame rate to %d fps. The actual " 749 "frame rate is %d", mFrameRate, frameRate); 750 } 751 752 CHECK_EQ(OK, mCamera->setPreviewDisplay(mPreviewSurface)); 753 IPCThreadState::self()->restoreCallingIdentity(token); 754 755 sp<CameraSource> cameraSource = 756 CameraSource::CreateFromCamera(mCamera); 757 758 CHECK(cameraSource != NULL); 759 760 sp<MetaData> enc_meta = new MetaData; 761 enc_meta->setInt32(kKeyBitRate, mVideoBitRate); 762 enc_meta->setInt32(kKeySampleRate, mFrameRate); 763 764 switch (mVideoEncoder) { 765 case VIDEO_ENCODER_H263: 766 enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263); 767 break; 768 769 case VIDEO_ENCODER_MPEG_4_SP: 770 enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); 771 break; 772 773 case VIDEO_ENCODER_H264: 774 enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); 775 break; 776 777 default: 778 CHECK(!"Should not be here, unsupported video encoding."); 779 break; 780 } 781 782 sp<MetaData> meta = cameraSource->getFormat(); 783 784 int32_t width, height, stride, sliceHeight; 785 CHECK(meta->findInt32(kKeyWidth, &width)); 786 CHECK(meta->findInt32(kKeyHeight, &height)); 787 CHECK(meta->findInt32(kKeyStride, &stride)); 788 CHECK(meta->findInt32(kKeySliceHeight, &sliceHeight)); 789 790 enc_meta->setInt32(kKeyWidth, width); 791 enc_meta->setInt32(kKeyHeight, height); 792 enc_meta->setInt32(kKeyIFramesInterval, mIFramesInterval); 793 enc_meta->setInt32(kKeyStride, stride); 794 enc_meta->setInt32(kKeySliceHeight, sliceHeight); 795 796 OMXClient client; 797 CHECK_EQ(client.connect(), OK); 798 799 sp<MediaSource> encoder = 800 OMXCodec::Create( 801 client.interface(), enc_meta, 802 true /* createEncoder */, cameraSource); 803 804 CHECK(mOutputFd >= 0); 805 totalBitRate += mVideoBitRate; 806 mWriter->addSource(encoder); 807 } 808 809 { 810 // MPEGWriter specific handling 811 MPEG4Writer *writer = ((MPEG4Writer *) mWriter.get()); 812 writer->setInterleaveDuration(mInterleaveDurationUs); 813 } 814 815 if (mMaxFileDurationUs != 0) { 816 mWriter->setMaxFileDuration(mMaxFileDurationUs); 817 } 818 if (mMaxFileSizeBytes != 0) { 819 mWriter->setMaxFileSize(mMaxFileSizeBytes); 820 } 821 mWriter->setListener(mListener); 822 sp<MetaData> meta = new MetaData; 823 meta->setInt64(kKeyTime, systemTime() / 1000); 824 meta->setInt32(kKeyFileType, mOutputFormat); 825 meta->setInt32(kKeyBitRate, totalBitRate); 826 meta->setInt32(kKey64BitFileOffset, mUse64BitFileOffset); 827 if (mTrackEveryNumberOfFrames > 0) { 828 meta->setInt32(kKeyTrackFrameStatus, mTrackEveryNumberOfFrames); 829 } 830 if (mTrackEveryTimeDurationUs > 0) { 831 meta->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs); 832 } 833 mWriter->start(meta.get()); 834 return OK; 835} 836 837status_t StagefrightRecorder::pause() { 838 if (mWriter == NULL) { 839 return UNKNOWN_ERROR; 840 } 841 mWriter->pause(); 842 return OK; 843} 844 845status_t StagefrightRecorder::stop() { 846 if (mWriter == NULL) { 847 return UNKNOWN_ERROR; 848 } 849 850 mWriter->stop(); 851 mWriter = NULL; 852 853 return OK; 854} 855 856status_t StagefrightRecorder::close() { 857 stop(); 858 859 if (mCamera != 0) { 860 int64_t token = IPCThreadState::self()->clearCallingIdentity(); 861 if ((mFlags & FLAGS_HOT_CAMERA) == 0) { 862 LOGV("Camera was cold when we started, stopping preview"); 863 mCamera->stopPreview(); 864 } 865 mCamera->unlock(); 866 mCamera = NULL; 867 IPCThreadState::self()->restoreCallingIdentity(token); 868 mFlags = 0; 869 } 870 return OK; 871} 872 873status_t StagefrightRecorder::reset() { 874 stop(); 875 876 // No audio or video source by default 877 mAudioSource = AUDIO_SOURCE_LIST_END; 878 mVideoSource = VIDEO_SOURCE_LIST_END; 879 880 // Default parameters 881 mOutputFormat = OUTPUT_FORMAT_THREE_GPP; 882 mAudioEncoder = AUDIO_ENCODER_AMR_NB; 883 mVideoEncoder = VIDEO_ENCODER_H263; 884 mVideoWidth = 176; 885 mVideoHeight = 144; 886 mFrameRate = 20; 887 mVideoBitRate = 192000; 888 mSampleRate = 8000; 889 mAudioChannels = 1; 890 mAudioBitRate = 12200; 891 mInterleaveDurationUs = 0; 892 mIFramesInterval = 1; 893 mAudioSourceNode = 0; 894 mUse64BitFileOffset = false; 895 mCameraId = 0; 896 mTrackEveryNumberOfFrames = 0; 897 mTrackEveryTimeDurationUs = 0; 898 mEncoderProfiles = MediaProfiles::getInstance(); 899 900 mOutputFd = -1; 901 mFlags = 0; 902 903 return OK; 904} 905 906status_t StagefrightRecorder::getMaxAmplitude(int *max) { 907 if (mAudioSourceNode != 0) { 908 *max = mAudioSourceNode->getMaxAmplitude(); 909 } else { 910 *max = 0; 911 } 912 913 return OK; 914} 915 916} // namespace android 917