StagefrightRecorder.cpp revision ca2fa61ef03cac008ea86e6fe16b2e5f9f1a2be3
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/CameraSourceTimeLapse.h> 28#include <media/stagefright/MPEG4Writer.h> 29#include <media/stagefright/MediaDebug.h> 30#include <media/stagefright/MediaDefs.h> 31#include <media/stagefright/MetaData.h> 32#include <media/stagefright/OMXClient.h> 33#include <media/stagefright/OMXCodec.h> 34#include <media/MediaProfiles.h> 35#include <camera/ICamera.h> 36#include <camera/Camera.h> 37#include <camera/CameraParameters.h> 38#include <surfaceflinger/ISurface.h> 39#include <utils/Errors.h> 40#include <sys/types.h> 41#include <ctype.h> 42#include <unistd.h> 43 44#include "ARTPWriter.h" 45 46namespace android { 47 48StagefrightRecorder::StagefrightRecorder() 49 : mWriter(NULL), 50 mOutputFd(-1) { 51 52 LOGV("Constructor"); 53 reset(); 54} 55 56StagefrightRecorder::~StagefrightRecorder() { 57 LOGV("Destructor"); 58 stop(); 59 60 if (mOutputFd >= 0) { 61 ::close(mOutputFd); 62 mOutputFd = -1; 63 } 64} 65 66status_t StagefrightRecorder::init() { 67 LOGV("init"); 68 return OK; 69} 70 71status_t StagefrightRecorder::setAudioSource(audio_source as) { 72 LOGV("setAudioSource: %d", as); 73 if (as < AUDIO_SOURCE_DEFAULT || 74 as >= AUDIO_SOURCE_LIST_END) { 75 LOGE("Invalid audio source: %d", as); 76 return BAD_VALUE; 77 } 78 79 if (as == AUDIO_SOURCE_DEFAULT) { 80 mAudioSource = AUDIO_SOURCE_MIC; 81 } else { 82 mAudioSource = as; 83 } 84 85 return OK; 86} 87 88status_t StagefrightRecorder::setVideoSource(video_source vs) { 89 LOGV("setVideoSource: %d", vs); 90 if (vs < VIDEO_SOURCE_DEFAULT || 91 vs >= VIDEO_SOURCE_LIST_END) { 92 LOGE("Invalid video source: %d", vs); 93 return BAD_VALUE; 94 } 95 96 if (vs == VIDEO_SOURCE_DEFAULT) { 97 mVideoSource = VIDEO_SOURCE_CAMERA; 98 } else { 99 mVideoSource = vs; 100 } 101 102 return OK; 103} 104 105status_t StagefrightRecorder::setOutputFormat(output_format of) { 106 LOGV("setOutputFormat: %d", of); 107 if (of < OUTPUT_FORMAT_DEFAULT || 108 of >= OUTPUT_FORMAT_LIST_END) { 109 LOGE("Invalid output format: %d", of); 110 return BAD_VALUE; 111 } 112 113 if (of == OUTPUT_FORMAT_DEFAULT) { 114 mOutputFormat = OUTPUT_FORMAT_THREE_GPP; 115 } else { 116 mOutputFormat = of; 117 } 118 119 return OK; 120} 121 122status_t StagefrightRecorder::setAudioEncoder(audio_encoder ae) { 123 LOGV("setAudioEncoder: %d", ae); 124 if (ae < AUDIO_ENCODER_DEFAULT || 125 ae >= AUDIO_ENCODER_LIST_END) { 126 LOGE("Invalid audio encoder: %d", ae); 127 return BAD_VALUE; 128 } 129 130 if (ae == AUDIO_ENCODER_DEFAULT) { 131 mAudioEncoder = AUDIO_ENCODER_AMR_NB; 132 } else { 133 mAudioEncoder = ae; 134 } 135 136 return OK; 137} 138 139status_t StagefrightRecorder::setVideoEncoder(video_encoder ve) { 140 LOGV("setVideoEncoder: %d", ve); 141 if (ve < VIDEO_ENCODER_DEFAULT || 142 ve >= VIDEO_ENCODER_LIST_END) { 143 LOGE("Invalid video encoder: %d", ve); 144 return BAD_VALUE; 145 } 146 147 if (ve == VIDEO_ENCODER_DEFAULT) { 148 mVideoEncoder = VIDEO_ENCODER_H263; 149 } else { 150 mVideoEncoder = ve; 151 } 152 153 return OK; 154} 155 156status_t StagefrightRecorder::setVideoSize(int width, int height) { 157 LOGV("setVideoSize: %dx%d", width, height); 158 if (width <= 0 || height <= 0) { 159 LOGE("Invalid video size: %dx%d", width, height); 160 return BAD_VALUE; 161 } 162 163 // Additional check on the dimension will be performed later 164 mVideoWidth = width; 165 mVideoHeight = height; 166 167 return OK; 168} 169 170status_t StagefrightRecorder::setVideoFrameRate(int frames_per_second) { 171 LOGV("setVideoFrameRate: %d", frames_per_second); 172 if (frames_per_second <= 0 || frames_per_second > 30) { 173 LOGE("Invalid video frame rate: %d", frames_per_second); 174 return BAD_VALUE; 175 } 176 177 // Additional check on the frame rate will be performed later 178 mFrameRate = frames_per_second; 179 180 return OK; 181} 182 183status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) { 184 LOGV("setCamera"); 185 if (camera == 0) { 186 LOGE("camera is NULL"); 187 return BAD_VALUE; 188 } 189 190 int64_t token = IPCThreadState::self()->clearCallingIdentity(); 191 mFlags &= ~FLAGS_HOT_CAMERA; 192 mCamera = Camera::create(camera); 193 if (mCamera == 0) { 194 LOGE("Unable to connect to camera"); 195 IPCThreadState::self()->restoreCallingIdentity(token); 196 return -EBUSY; 197 } 198 199 LOGV("Connected to camera"); 200 if (mCamera->previewEnabled()) { 201 LOGV("camera is hot"); 202 mFlags |= FLAGS_HOT_CAMERA; 203 } 204 IPCThreadState::self()->restoreCallingIdentity(token); 205 206 return OK; 207} 208 209status_t StagefrightRecorder::setPreviewSurface(const sp<ISurface> &surface) { 210 LOGV("setPreviewSurface: %p", surface.get()); 211 mPreviewSurface = surface; 212 213 return OK; 214} 215 216status_t StagefrightRecorder::setOutputFile(const char *path) { 217 LOGE("setOutputFile(const char*) must not be called"); 218 // We don't actually support this at all, as the media_server process 219 // no longer has permissions to create files. 220 221 return -EPERM; 222} 223 224status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t length) { 225 LOGV("setOutputFile: %d, %lld, %lld", fd, offset, length); 226 // These don't make any sense, do they? 227 CHECK_EQ(offset, 0); 228 CHECK_EQ(length, 0); 229 230 if (fd < 0) { 231 LOGE("Invalid file descriptor: %d", fd); 232 return -EBADF; 233 } 234 235 if (mOutputFd >= 0) { 236 ::close(mOutputFd); 237 } 238 mOutputFd = dup(fd); 239 240 return OK; 241} 242 243// Attempt to parse an int64 literal optionally surrounded by whitespace, 244// returns true on success, false otherwise. 245static bool safe_strtoi64(const char *s, int64_t *val) { 246 char *end; 247 *val = strtoll(s, &end, 10); 248 249 if (end == s || errno == ERANGE) { 250 return false; 251 } 252 253 // Skip trailing whitespace 254 while (isspace(*end)) { 255 ++end; 256 } 257 258 // For a successful return, the string must contain nothing but a valid 259 // int64 literal optionally surrounded by whitespace. 260 261 return *end == '\0'; 262} 263 264// Return true if the value is in [0, 0x007FFFFFFF] 265static bool safe_strtoi32(const char *s, int32_t *val) { 266 int64_t temp; 267 if (safe_strtoi64(s, &temp)) { 268 if (temp >= 0 && temp <= 0x007FFFFFFF) { 269 *val = static_cast<int32_t>(temp); 270 return true; 271 } 272 } 273 return false; 274} 275 276// Trim both leading and trailing whitespace from the given string. 277static void TrimString(String8 *s) { 278 size_t num_bytes = s->bytes(); 279 const char *data = s->string(); 280 281 size_t leading_space = 0; 282 while (leading_space < num_bytes && isspace(data[leading_space])) { 283 ++leading_space; 284 } 285 286 size_t i = num_bytes; 287 while (i > leading_space && isspace(data[i - 1])) { 288 --i; 289 } 290 291 s->setTo(String8(&data[leading_space], i - leading_space)); 292} 293 294status_t StagefrightRecorder::setParamAudioSamplingRate(int32_t sampleRate) { 295 LOGV("setParamAudioSamplingRate: %d", sampleRate); 296 if (sampleRate <= 0) { 297 LOGE("Invalid audio sampling rate: %d", sampleRate); 298 return BAD_VALUE; 299 } 300 301 // Additional check on the sample rate will be performed later. 302 mSampleRate = sampleRate; 303 return OK; 304} 305 306status_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) { 307 LOGV("setParamAudioNumberOfChannels: %d", channels); 308 if (channels <= 0 || channels >= 3) { 309 LOGE("Invalid number of audio channels: %d", channels); 310 return BAD_VALUE; 311 } 312 313 // Additional check on the number of channels will be performed later. 314 mAudioChannels = channels; 315 return OK; 316} 317 318status_t StagefrightRecorder::setParamAudioEncodingBitRate(int32_t bitRate) { 319 LOGV("setParamAudioEncodingBitRate: %d", bitRate); 320 if (bitRate <= 0) { 321 LOGE("Invalid audio encoding bit rate: %d", bitRate); 322 return BAD_VALUE; 323 } 324 325 // The target bit rate may not be exactly the same as the requested. 326 // It depends on many factors, such as rate control, and the bit rate 327 // range that a specific encoder supports. The mismatch between the 328 // the target and requested bit rate will NOT be treated as an error. 329 mAudioBitRate = bitRate; 330 return OK; 331} 332 333status_t StagefrightRecorder::setParamVideoEncodingBitRate(int32_t bitRate) { 334 LOGV("setParamVideoEncodingBitRate: %d", bitRate); 335 if (bitRate <= 0) { 336 LOGE("Invalid video encoding bit rate: %d", bitRate); 337 return BAD_VALUE; 338 } 339 340 // The target bit rate may not be exactly the same as the requested. 341 // It depends on many factors, such as rate control, and the bit rate 342 // range that a specific encoder supports. The mismatch between the 343 // the target and requested bit rate will NOT be treated as an error. 344 mVideoBitRate = bitRate; 345 return OK; 346} 347 348status_t StagefrightRecorder::setParamMaxFileDurationUs(int64_t timeUs) { 349 LOGV("setParamMaxFileDurationUs: %lld us", timeUs); 350 if (timeUs <= 100000LL) { // XXX: 100 milli-seconds 351 LOGE("Max file duration is too short: %lld us", timeUs); 352 return BAD_VALUE; 353 } 354 mMaxFileDurationUs = timeUs; 355 return OK; 356} 357 358status_t StagefrightRecorder::setParamMaxFileSizeBytes(int64_t bytes) { 359 LOGV("setParamMaxFileSizeBytes: %lld bytes", bytes); 360 if (bytes <= 1024) { // XXX: 1 kB 361 LOGE("Max file size is too small: %lld bytes", bytes); 362 return BAD_VALUE; 363 } 364 mMaxFileSizeBytes = bytes; 365 return OK; 366} 367 368status_t StagefrightRecorder::setParamInterleaveDuration(int32_t durationUs) { 369 LOGV("setParamInterleaveDuration: %d", durationUs); 370 if (durationUs <= 500000) { // 500 ms 371 // If interleave duration is too small, it is very inefficient to do 372 // interleaving since the metadata overhead will count for a significant 373 // portion of the saved contents 374 LOGE("Audio/video interleave duration is too small: %d us", durationUs); 375 return BAD_VALUE; 376 } else if (durationUs >= 10000000) { // 10 seconds 377 // If interleaving duration is too large, it can cause the recording 378 // session to use too much memory since we have to save the output 379 // data before we write them out 380 LOGE("Audio/video interleave duration is too large: %d us", durationUs); 381 return BAD_VALUE; 382 } 383 mInterleaveDurationUs = durationUs; 384 return OK; 385} 386 387// If seconds < 0, only the first frame is I frame, and rest are all P frames 388// If seconds == 0, all frames are encoded as I frames. No P frames 389// If seconds > 0, it is the time spacing (seconds) between 2 neighboring I frames 390status_t StagefrightRecorder::setParamVideoIFramesInterval(int32_t seconds) { 391 LOGV("setParamVideoIFramesInterval: %d seconds", seconds); 392 mIFramesIntervalSec = seconds; 393 return OK; 394} 395 396status_t StagefrightRecorder::setParam64BitFileOffset(bool use64Bit) { 397 LOGV("setParam64BitFileOffset: %s", 398 use64Bit? "use 64 bit file offset": "use 32 bit file offset"); 399 mUse64BitFileOffset = use64Bit; 400 return OK; 401} 402 403status_t StagefrightRecorder::setParamVideoCameraId(int32_t cameraId) { 404 LOGV("setParamVideoCameraId: %d", cameraId); 405 if (cameraId < 0) { 406 return BAD_VALUE; 407 } 408 mCameraId = cameraId; 409 return OK; 410} 411 412status_t StagefrightRecorder::setParamTrackTimeStatus(int64_t timeDurationUs) { 413 LOGV("setParamTrackTimeStatus: %lld", timeDurationUs); 414 if (timeDurationUs < 20000) { // Infeasible if shorter than 20 ms? 415 LOGE("Tracking time duration too short: %lld us", timeDurationUs); 416 return BAD_VALUE; 417 } 418 mTrackEveryTimeDurationUs = timeDurationUs; 419 return OK; 420} 421 422status_t StagefrightRecorder::setParamVideoEncoderProfile(int32_t profile) { 423 LOGV("setParamVideoEncoderProfile: %d", profile); 424 425 // Additional check will be done later when we load the encoder. 426 // For now, we are accepting values defined in OpenMAX IL. 427 mVideoEncoderProfile = profile; 428 return OK; 429} 430 431status_t StagefrightRecorder::setParamVideoEncoderLevel(int32_t level) { 432 LOGV("setParamVideoEncoderLevel: %d", level); 433 434 // Additional check will be done later when we load the encoder. 435 // For now, we are accepting values defined in OpenMAX IL. 436 mVideoEncoderLevel = level; 437 return OK; 438} 439 440status_t StagefrightRecorder::setParamMovieTimeScale(int32_t timeScale) { 441 LOGV("setParamMovieTimeScale: %d", timeScale); 442 443 // The range is set to be the same as the audio's time scale range 444 // since audio's time scale has a wider range. 445 if (timeScale < 600 || timeScale > 96000) { 446 LOGE("Time scale (%d) for movie is out of range [600, 96000]", timeScale); 447 return BAD_VALUE; 448 } 449 mMovieTimeScale = timeScale; 450 return OK; 451} 452 453status_t StagefrightRecorder::setParamVideoTimeScale(int32_t timeScale) { 454 LOGV("setParamVideoTimeScale: %d", timeScale); 455 456 // 60000 is chosen to make sure that each video frame from a 60-fps 457 // video has 1000 ticks. 458 if (timeScale < 600 || timeScale > 60000) { 459 LOGE("Time scale (%d) for video is out of range [600, 60000]", timeScale); 460 return BAD_VALUE; 461 } 462 mVideoTimeScale = timeScale; 463 return OK; 464} 465 466status_t StagefrightRecorder::setParamAudioTimeScale(int32_t timeScale) { 467 LOGV("setParamAudioTimeScale: %d", timeScale); 468 469 // 96000 Hz is the highest sampling rate support in AAC. 470 if (timeScale < 600 || timeScale > 96000) { 471 LOGE("Time scale (%d) for audio is out of range [600, 96000]", timeScale); 472 return BAD_VALUE; 473 } 474 mAudioTimeScale = timeScale; 475 return OK; 476} 477 478status_t StagefrightRecorder::setParamTimeLapseEnable(int32_t timeLapseEnable) { 479 LOGV("setParamTimeLapseEnable: %d", timeLapseEnable); 480 481 if(timeLapseEnable == 0) { 482 mCaptureTimeLapse = false; 483 } else if (timeLapseEnable == 1) { 484 mCaptureTimeLapse = true; 485 } else { 486 return BAD_VALUE; 487 } 488 return OK; 489} 490 491status_t StagefrightRecorder::setParamUseStillCameraForTimeLapse(int32_t useStillCamera) { 492 LOGV("setParamUseStillCameraForTimeLapse: %d", useStillCamera); 493 494 if(useStillCamera == 0) { 495 mUseStillCameraForTimeLapse= false; 496 } else if (useStillCamera == 1) { 497 mUseStillCameraForTimeLapse= true; 498 } else { 499 return BAD_VALUE; 500 } 501 return OK; 502} 503 504status_t StagefrightRecorder::setParamTimeBetweenTimeLapseFrameCapture(int64_t timeUs) { 505 LOGV("setParamTimeBetweenTimeLapseFrameCapture: %lld us", timeUs); 506 507 // Not allowing time more than a day 508 if (timeUs <= 0 || timeUs > 86400*1E6) { 509 LOGE("Time between time lapse frame capture (%lld) is out of range [0, 1 Day]", timeUs); 510 return BAD_VALUE; 511 } 512 513 mTimeBetweenTimeLapseFrameCaptureUs = timeUs; 514 return OK; 515} 516 517status_t StagefrightRecorder::setParameter( 518 const String8 &key, const String8 &value) { 519 LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string()); 520 if (key == "max-duration") { 521 int64_t max_duration_ms; 522 if (safe_strtoi64(value.string(), &max_duration_ms)) { 523 return setParamMaxFileDurationUs(1000LL * max_duration_ms); 524 } 525 } else if (key == "max-filesize") { 526 int64_t max_filesize_bytes; 527 if (safe_strtoi64(value.string(), &max_filesize_bytes)) { 528 return setParamMaxFileSizeBytes(max_filesize_bytes); 529 } 530 } else if (key == "interleave-duration-us") { 531 int32_t durationUs; 532 if (safe_strtoi32(value.string(), &durationUs)) { 533 return setParamInterleaveDuration(durationUs); 534 } 535 } else if (key == "param-movie-time-scale") { 536 int32_t timeScale; 537 if (safe_strtoi32(value.string(), &timeScale)) { 538 return setParamMovieTimeScale(timeScale); 539 } 540 } else if (key == "param-use-64bit-offset") { 541 int32_t use64BitOffset; 542 if (safe_strtoi32(value.string(), &use64BitOffset)) { 543 return setParam64BitFileOffset(use64BitOffset != 0); 544 } 545 } else if (key == "param-track-time-status") { 546 int64_t timeDurationUs; 547 if (safe_strtoi64(value.string(), &timeDurationUs)) { 548 return setParamTrackTimeStatus(timeDurationUs); 549 } 550 } else if (key == "audio-param-sampling-rate") { 551 int32_t sampling_rate; 552 if (safe_strtoi32(value.string(), &sampling_rate)) { 553 return setParamAudioSamplingRate(sampling_rate); 554 } 555 } else if (key == "audio-param-number-of-channels") { 556 int32_t number_of_channels; 557 if (safe_strtoi32(value.string(), &number_of_channels)) { 558 return setParamAudioNumberOfChannels(number_of_channels); 559 } 560 } else if (key == "audio-param-encoding-bitrate") { 561 int32_t audio_bitrate; 562 if (safe_strtoi32(value.string(), &audio_bitrate)) { 563 return setParamAudioEncodingBitRate(audio_bitrate); 564 } 565 } else if (key == "audio-param-time-scale") { 566 int32_t timeScale; 567 if (safe_strtoi32(value.string(), &timeScale)) { 568 return setParamAudioTimeScale(timeScale); 569 } 570 } else if (key == "video-param-encoding-bitrate") { 571 int32_t video_bitrate; 572 if (safe_strtoi32(value.string(), &video_bitrate)) { 573 return setParamVideoEncodingBitRate(video_bitrate); 574 } 575 } else if (key == "video-param-i-frames-interval") { 576 int32_t seconds; 577 if (safe_strtoi32(value.string(), &seconds)) { 578 return setParamVideoIFramesInterval(seconds); 579 } 580 } else if (key == "video-param-encoder-profile") { 581 int32_t profile; 582 if (safe_strtoi32(value.string(), &profile)) { 583 return setParamVideoEncoderProfile(profile); 584 } 585 } else if (key == "video-param-encoder-level") { 586 int32_t level; 587 if (safe_strtoi32(value.string(), &level)) { 588 return setParamVideoEncoderLevel(level); 589 } 590 } else if (key == "video-param-camera-id") { 591 int32_t cameraId; 592 if (safe_strtoi32(value.string(), &cameraId)) { 593 return setParamVideoCameraId(cameraId); 594 } 595 } else if (key == "video-param-time-scale") { 596 int32_t timeScale; 597 if (safe_strtoi32(value.string(), &timeScale)) { 598 return setParamVideoTimeScale(timeScale); 599 } 600 } else if (key == "time-lapse-enable") { 601 int32_t timeLapseEnable; 602 if (safe_strtoi32(value.string(), &timeLapseEnable)) { 603 return setParamTimeLapseEnable(timeLapseEnable); 604 } 605 } else if (key == "use-still-camera-for-time-lapse") { 606 int32_t useStillCamera; 607 if (safe_strtoi32(value.string(), &useStillCamera)) { 608 return setParamUseStillCameraForTimeLapse(useStillCamera); 609 } 610 } else if (key == "time-between-time-lapse-frame-capture") { 611 int64_t timeBetweenTimeLapseFrameCaptureMs; 612 if (safe_strtoi64(value.string(), &timeBetweenTimeLapseFrameCaptureMs)) { 613 return setParamTimeBetweenTimeLapseFrameCapture( 614 1000LL * timeBetweenTimeLapseFrameCaptureMs); 615 } 616 } else { 617 LOGE("setParameter: failed to find key %s", key.string()); 618 } 619 return BAD_VALUE; 620} 621 622status_t StagefrightRecorder::setParameters(const String8 ¶ms) { 623 LOGV("setParameters: %s", params.string()); 624 const char *cparams = params.string(); 625 const char *key_start = cparams; 626 for (;;) { 627 const char *equal_pos = strchr(key_start, '='); 628 if (equal_pos == NULL) { 629 LOGE("Parameters %s miss a value", cparams); 630 return BAD_VALUE; 631 } 632 String8 key(key_start, equal_pos - key_start); 633 TrimString(&key); 634 if (key.length() == 0) { 635 LOGE("Parameters %s contains an empty key", cparams); 636 return BAD_VALUE; 637 } 638 const char *value_start = equal_pos + 1; 639 const char *semicolon_pos = strchr(value_start, ';'); 640 String8 value; 641 if (semicolon_pos == NULL) { 642 value.setTo(value_start); 643 } else { 644 value.setTo(value_start, semicolon_pos - value_start); 645 } 646 if (setParameter(key, value) != OK) { 647 return BAD_VALUE; 648 } 649 if (semicolon_pos == NULL) { 650 break; // Reaches the end 651 } 652 key_start = semicolon_pos + 1; 653 } 654 return OK; 655} 656 657status_t StagefrightRecorder::setListener(const sp<IMediaRecorderClient> &listener) { 658 mListener = listener; 659 660 return OK; 661} 662 663status_t StagefrightRecorder::prepare() { 664 return OK; 665} 666 667status_t StagefrightRecorder::start() { 668 CHECK(mOutputFd >= 0); 669 670 if (mWriter != NULL) { 671 LOGE("File writer is not avaialble"); 672 return UNKNOWN_ERROR; 673 } 674 675 switch (mOutputFormat) { 676 case OUTPUT_FORMAT_DEFAULT: 677 case OUTPUT_FORMAT_THREE_GPP: 678 case OUTPUT_FORMAT_MPEG_4: 679 return startMPEG4Recording(); 680 681 case OUTPUT_FORMAT_AMR_NB: 682 case OUTPUT_FORMAT_AMR_WB: 683 return startAMRRecording(); 684 685 case OUTPUT_FORMAT_AAC_ADIF: 686 case OUTPUT_FORMAT_AAC_ADTS: 687 return startAACRecording(); 688 689 case OUTPUT_FORMAT_RTP_AVP: 690 return startRTPRecording(); 691 692 default: 693 LOGE("Unsupported output file format: %d", mOutputFormat); 694 return UNKNOWN_ERROR; 695 } 696} 697 698sp<MediaSource> StagefrightRecorder::createAudioSource() { 699 sp<AudioSource> audioSource = 700 new AudioSource( 701 mAudioSource, 702 mSampleRate, 703 mAudioChannels); 704 705 status_t err = audioSource->initCheck(); 706 707 if (err != OK) { 708 LOGE("audio source is not initialized"); 709 return NULL; 710 } 711 712 sp<MetaData> encMeta = new MetaData; 713 const char *mime; 714 switch (mAudioEncoder) { 715 case AUDIO_ENCODER_AMR_NB: 716 case AUDIO_ENCODER_DEFAULT: 717 mime = MEDIA_MIMETYPE_AUDIO_AMR_NB; 718 break; 719 case AUDIO_ENCODER_AMR_WB: 720 mime = MEDIA_MIMETYPE_AUDIO_AMR_WB; 721 break; 722 case AUDIO_ENCODER_AAC: 723 mime = MEDIA_MIMETYPE_AUDIO_AAC; 724 break; 725 default: 726 LOGE("Unknown audio encoder: %d", mAudioEncoder); 727 return NULL; 728 } 729 encMeta->setCString(kKeyMIMEType, mime); 730 731 int32_t maxInputSize; 732 CHECK(audioSource->getFormat()->findInt32( 733 kKeyMaxInputSize, &maxInputSize)); 734 735 encMeta->setInt32(kKeyMaxInputSize, maxInputSize); 736 encMeta->setInt32(kKeyChannelCount, mAudioChannels); 737 encMeta->setInt32(kKeySampleRate, mSampleRate); 738 encMeta->setInt32(kKeyBitRate, mAudioBitRate); 739 encMeta->setInt32(kKeyTimeScale, mAudioTimeScale); 740 741 OMXClient client; 742 CHECK_EQ(client.connect(), OK); 743 744 sp<MediaSource> audioEncoder = 745 OMXCodec::Create(client.interface(), encMeta, 746 true /* createEncoder */, audioSource); 747 mAudioSourceNode = audioSource; 748 749 return audioEncoder; 750} 751 752status_t StagefrightRecorder::startAACRecording() { 753 CHECK(mOutputFormat == OUTPUT_FORMAT_AAC_ADIF || 754 mOutputFormat == OUTPUT_FORMAT_AAC_ADTS); 755 756 CHECK(mAudioEncoder == AUDIO_ENCODER_AAC); 757 CHECK(mAudioSource != AUDIO_SOURCE_LIST_END); 758 759 CHECK(0 == "AACWriter is not implemented yet"); 760 761 return OK; 762} 763 764status_t StagefrightRecorder::startAMRRecording() { 765 CHECK(mOutputFormat == OUTPUT_FORMAT_AMR_NB || 766 mOutputFormat == OUTPUT_FORMAT_AMR_WB); 767 768 if (mOutputFormat == OUTPUT_FORMAT_AMR_NB) { 769 if (mAudioEncoder != AUDIO_ENCODER_DEFAULT && 770 mAudioEncoder != AUDIO_ENCODER_AMR_NB) { 771 LOGE("Invalid encoder %d used for AMRNB recording", 772 mAudioEncoder); 773 return BAD_VALUE; 774 } 775 if (mSampleRate != 8000) { 776 LOGE("Invalid sampling rate %d used for AMRNB recording", 777 mSampleRate); 778 return BAD_VALUE; 779 } 780 } else { // mOutputFormat must be OUTPUT_FORMAT_AMR_WB 781 if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) { 782 LOGE("Invlaid encoder %d used for AMRWB recording", 783 mAudioEncoder); 784 return BAD_VALUE; 785 } 786 if (mSampleRate != 16000) { 787 LOGE("Invalid sample rate %d used for AMRWB recording", 788 mSampleRate); 789 return BAD_VALUE; 790 } 791 } 792 if (mAudioChannels != 1) { 793 LOGE("Invalid number of audio channels %d used for amr recording", 794 mAudioChannels); 795 return BAD_VALUE; 796 } 797 798 if (mAudioSource >= AUDIO_SOURCE_LIST_END) { 799 LOGE("Invalid audio source: %d", mAudioSource); 800 return BAD_VALUE; 801 } 802 803 sp<MediaSource> audioEncoder = createAudioSource(); 804 805 if (audioEncoder == NULL) { 806 return UNKNOWN_ERROR; 807 } 808 809 mWriter = new AMRWriter(dup(mOutputFd)); 810 mWriter->addSource(audioEncoder); 811 812 if (mMaxFileDurationUs != 0) { 813 mWriter->setMaxFileDuration(mMaxFileDurationUs); 814 } 815 if (mMaxFileSizeBytes != 0) { 816 mWriter->setMaxFileSize(mMaxFileSizeBytes); 817 } 818 mWriter->setListener(mListener); 819 mWriter->start(); 820 821 return OK; 822} 823 824status_t StagefrightRecorder::startRTPRecording() { 825 CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_RTP_AVP); 826 827 if ((mAudioSource != AUDIO_SOURCE_LIST_END 828 && mVideoSource != VIDEO_SOURCE_LIST_END) 829 || (mAudioSource == AUDIO_SOURCE_LIST_END 830 && mVideoSource == VIDEO_SOURCE_LIST_END)) { 831 // Must have exactly one source. 832 return BAD_VALUE; 833 } 834 835 if (mOutputFd < 0) { 836 return BAD_VALUE; 837 } 838 839 sp<MediaSource> source; 840 841 if (mAudioSource != AUDIO_SOURCE_LIST_END) { 842 source = createAudioSource(); 843 } else { 844 status_t err = setupVideoEncoder(&source); 845 if (err != OK) { 846 return err; 847 } 848 } 849 850 mWriter = new ARTPWriter(dup(mOutputFd)); 851 mWriter->addSource(source); 852 mWriter->setListener(mListener); 853 854 return mWriter->start(); 855} 856 857void StagefrightRecorder::clipVideoFrameRate() { 858 LOGV("clipVideoFrameRate: encoder %d", mVideoEncoder); 859 int minFrameRate = mEncoderProfiles->getVideoEncoderParamByName( 860 "enc.vid.fps.min", mVideoEncoder); 861 int maxFrameRate = mEncoderProfiles->getVideoEncoderParamByName( 862 "enc.vid.fps.max", mVideoEncoder); 863 if (mFrameRate < minFrameRate) { 864 LOGW("Intended video encoding frame rate (%d fps) is too small" 865 " and will be set to (%d fps)", mFrameRate, minFrameRate); 866 mFrameRate = minFrameRate; 867 } else if (mFrameRate > maxFrameRate) { 868 LOGW("Intended video encoding frame rate (%d fps) is too large" 869 " and will be set to (%d fps)", mFrameRate, maxFrameRate); 870 mFrameRate = maxFrameRate; 871 } 872} 873 874void StagefrightRecorder::clipVideoBitRate() { 875 LOGV("clipVideoBitRate: encoder %d", mVideoEncoder); 876 int minBitRate = mEncoderProfiles->getVideoEncoderParamByName( 877 "enc.vid.bps.min", mVideoEncoder); 878 int maxBitRate = mEncoderProfiles->getVideoEncoderParamByName( 879 "enc.vid.bps.max", mVideoEncoder); 880 if (mVideoBitRate < minBitRate) { 881 LOGW("Intended video encoding bit rate (%d bps) is too small" 882 " and will be set to (%d bps)", mVideoBitRate, minBitRate); 883 mVideoBitRate = minBitRate; 884 } else if (mVideoBitRate > maxBitRate) { 885 LOGW("Intended video encoding bit rate (%d bps) is too large" 886 " and will be set to (%d bps)", mVideoBitRate, maxBitRate); 887 mVideoBitRate = maxBitRate; 888 } 889} 890 891void StagefrightRecorder::clipVideoFrameWidth() { 892 LOGV("clipVideoFrameWidth: encoder %d", mVideoEncoder); 893 int minFrameWidth = mEncoderProfiles->getVideoEncoderParamByName( 894 "enc.vid.width.min", mVideoEncoder); 895 int maxFrameWidth = mEncoderProfiles->getVideoEncoderParamByName( 896 "enc.vid.width.max", mVideoEncoder); 897 if (mVideoWidth < minFrameWidth) { 898 LOGW("Intended video encoding frame width (%d) is too small" 899 " and will be set to (%d)", mVideoWidth, minFrameWidth); 900 mVideoWidth = minFrameWidth; 901 } else if (mVideoWidth > maxFrameWidth) { 902 LOGW("Intended video encoding frame width (%d) is too large" 903 " and will be set to (%d)", mVideoWidth, maxFrameWidth); 904 mVideoWidth = maxFrameWidth; 905 } 906} 907 908status_t StagefrightRecorder::setupCameraSource() { 909 if (!mCaptureTimeLapse) { 910 // Dont clip for time lapse capture as encoder will have enough 911 // time to encode because of slow capture rate of time lapse. 912 clipVideoBitRate(); 913 clipVideoFrameRate(); 914 clipVideoFrameWidth(); 915 clipVideoFrameHeight(); 916 } 917 918 int64_t token = IPCThreadState::self()->clearCallingIdentity(); 919 if (mCamera == 0) { 920 mCamera = Camera::connect(mCameraId); 921 if (mCamera == 0) { 922 LOGE("Camera connection could not be established."); 923 return -EBUSY; 924 } 925 mFlags &= ~FLAGS_HOT_CAMERA; 926 mCamera->lock(); 927 } 928 929 // Set the actual video recording frame size 930 CameraParameters params(mCamera->getParameters()); 931 932 // dont change the preview size when using still camera for time lapse 933 // as mVideoWidth, mVideoHeight may correspond to HD resolution not 934 // supported by the video camera. 935 if (!(mCaptureTimeLapse && mUseStillCameraForTimeLapse)) { 936 params.setPreviewSize(mVideoWidth, mVideoHeight); 937 } 938 939 params.setPreviewFrameRate(mFrameRate); 940 String8 s = params.flatten(); 941 if (OK != mCamera->setParameters(s)) { 942 LOGE("Could not change settings." 943 " Someone else is using camera %d?", mCameraId); 944 return -EBUSY; 945 } 946 CameraParameters newCameraParams(mCamera->getParameters()); 947 948 // Check on video frame size 949 int frameWidth = 0, frameHeight = 0; 950 newCameraParams.getPreviewSize(&frameWidth, &frameHeight); 951 if (!(mCaptureTimeLapse && mUseStillCameraForTimeLapse) && 952 (frameWidth < 0 || frameWidth != mVideoWidth || 953 frameHeight < 0 || frameHeight != mVideoHeight)) { 954 LOGE("Failed to set the video frame size to %dx%d", 955 mVideoWidth, mVideoHeight); 956 IPCThreadState::self()->restoreCallingIdentity(token); 957 return UNKNOWN_ERROR; 958 } 959 960 // Check on video frame rate 961 int frameRate = newCameraParams.getPreviewFrameRate(); 962 if (frameRate < 0 || (frameRate - mFrameRate) != 0) { 963 LOGE("Failed to set frame rate to %d fps. The actual " 964 "frame rate is %d", mFrameRate, frameRate); 965 } 966 967 // This CHECK is good, since we just passed the lock/unlock 968 // check earlier by calling mCamera->setParameters(). 969 CHECK_EQ(OK, mCamera->setPreviewDisplay(mPreviewSurface)); 970 IPCThreadState::self()->restoreCallingIdentity(token); 971 return OK; 972} 973 974void StagefrightRecorder::clipVideoFrameHeight() { 975 LOGV("clipVideoFrameHeight: encoder %d", mVideoEncoder); 976 int minFrameHeight = mEncoderProfiles->getVideoEncoderParamByName( 977 "enc.vid.height.min", mVideoEncoder); 978 int maxFrameHeight = mEncoderProfiles->getVideoEncoderParamByName( 979 "enc.vid.height.max", mVideoEncoder); 980 if (mVideoHeight < minFrameHeight) { 981 LOGW("Intended video encoding frame height (%d) is too small" 982 " and will be set to (%d)", mVideoHeight, minFrameHeight); 983 mVideoHeight = minFrameHeight; 984 } else if (mVideoHeight > maxFrameHeight) { 985 LOGW("Intended video encoding frame height (%d) is too large" 986 " and will be set to (%d)", mVideoHeight, maxFrameHeight); 987 mVideoHeight = maxFrameHeight; 988 } 989} 990 991status_t StagefrightRecorder::setupVideoEncoder(sp<MediaSource> *source) { 992 source->clear(); 993 994 status_t err = setupCameraSource(); 995 if (err != OK) return err; 996 997 sp<CameraSource> cameraSource = (mCaptureTimeLapse) ? 998 CameraSourceTimeLapse::CreateFromCamera(mCamera, mUseStillCameraForTimeLapse, 999 mTimeBetweenTimeLapseFrameCaptureUs, mVideoWidth, mVideoHeight, mFrameRate): 1000 CameraSource::CreateFromCamera(mCamera); 1001 CHECK(cameraSource != NULL); 1002 1003 sp<MetaData> enc_meta = new MetaData; 1004 enc_meta->setInt32(kKeyBitRate, mVideoBitRate); 1005 enc_meta->setInt32(kKeySampleRate, mFrameRate); 1006 1007 switch (mVideoEncoder) { 1008 case VIDEO_ENCODER_H263: 1009 enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263); 1010 break; 1011 1012 case VIDEO_ENCODER_MPEG_4_SP: 1013 enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); 1014 break; 1015 1016 case VIDEO_ENCODER_H264: 1017 enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); 1018 break; 1019 1020 default: 1021 CHECK(!"Should not be here, unsupported video encoding."); 1022 break; 1023 } 1024 1025 sp<MetaData> meta = cameraSource->getFormat(); 1026 1027 int32_t width, height, stride, sliceHeight, colorFormat; 1028 CHECK(meta->findInt32(kKeyWidth, &width)); 1029 CHECK(meta->findInt32(kKeyHeight, &height)); 1030 CHECK(meta->findInt32(kKeyStride, &stride)); 1031 CHECK(meta->findInt32(kKeySliceHeight, &sliceHeight)); 1032 CHECK(meta->findInt32(kKeyColorFormat, &colorFormat)); 1033 1034 enc_meta->setInt32(kKeyWidth, width); 1035 enc_meta->setInt32(kKeyHeight, height); 1036 enc_meta->setInt32(kKeyIFramesInterval, mIFramesIntervalSec); 1037 enc_meta->setInt32(kKeyStride, stride); 1038 enc_meta->setInt32(kKeySliceHeight, sliceHeight); 1039 enc_meta->setInt32(kKeyColorFormat, colorFormat); 1040 enc_meta->setInt32(kKeyTimeScale, mVideoTimeScale); 1041 if (mVideoEncoderProfile != -1) { 1042 enc_meta->setInt32(kKeyVideoProfile, mVideoEncoderProfile); 1043 } 1044 if (mVideoEncoderLevel != -1) { 1045 enc_meta->setInt32(kKeyVideoLevel, mVideoEncoderLevel); 1046 } 1047 1048 OMXClient client; 1049 CHECK_EQ(client.connect(), OK); 1050 1051 // Use software codec for time lapse 1052 uint32_t encoder_flags = (mCaptureTimeLapse) ? OMXCodec::kPreferSoftwareCodecs : 0; 1053 sp<MediaSource> encoder = OMXCodec::Create( 1054 client.interface(), enc_meta, 1055 true /* createEncoder */, cameraSource, 1056 NULL, encoder_flags); 1057 if (encoder == NULL) { 1058 return UNKNOWN_ERROR; 1059 } 1060 1061 *source = encoder; 1062 1063 return OK; 1064} 1065 1066status_t StagefrightRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) { 1067 sp<MediaSource> audioEncoder; 1068 switch(mAudioEncoder) { 1069 case AUDIO_ENCODER_AMR_NB: 1070 case AUDIO_ENCODER_AMR_WB: 1071 case AUDIO_ENCODER_AAC: 1072 audioEncoder = createAudioSource(); 1073 break; 1074 default: 1075 LOGE("Unsupported audio encoder: %d", mAudioEncoder); 1076 return UNKNOWN_ERROR; 1077 } 1078 1079 if (audioEncoder == NULL) { 1080 return UNKNOWN_ERROR; 1081 } 1082 1083 writer->addSource(audioEncoder); 1084 return OK; 1085} 1086 1087status_t StagefrightRecorder::startMPEG4Recording() { 1088 int32_t totalBitRate = 0; 1089 status_t err = OK; 1090 sp<MediaWriter> writer = new MPEG4Writer(dup(mOutputFd)); 1091 1092 // Add audio source first if it exists 1093 if (!mCaptureTimeLapse && (mAudioSource != AUDIO_SOURCE_LIST_END)) { 1094 err = setupAudioEncoder(writer); 1095 if (err != OK) return err; 1096 totalBitRate += mAudioBitRate; 1097 } 1098 if (mVideoSource == VIDEO_SOURCE_DEFAULT 1099 || mVideoSource == VIDEO_SOURCE_CAMERA) { 1100 sp<MediaSource> encoder; 1101 err = setupVideoEncoder(&encoder); 1102 if (err != OK) return err; 1103 writer->addSource(encoder); 1104 totalBitRate += mVideoBitRate; 1105 } 1106 1107 if (mInterleaveDurationUs > 0) { 1108 reinterpret_cast<MPEG4Writer *>(writer.get())-> 1109 setInterleaveDuration(mInterleaveDurationUs); 1110 } 1111 1112 if (mMaxFileDurationUs != 0) { 1113 writer->setMaxFileDuration(mMaxFileDurationUs); 1114 } 1115 if (mMaxFileSizeBytes != 0) { 1116 writer->setMaxFileSize(mMaxFileSizeBytes); 1117 } 1118 sp<MetaData> meta = new MetaData; 1119 meta->setInt64(kKeyTime, systemTime() / 1000); 1120 meta->setInt32(kKeyFileType, mOutputFormat); 1121 meta->setInt32(kKeyBitRate, totalBitRate); 1122 meta->setInt32(kKey64BitFileOffset, mUse64BitFileOffset); 1123 meta->setInt32(kKeyTimeScale, mMovieTimeScale); 1124 if (mTrackEveryTimeDurationUs > 0) { 1125 meta->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs); 1126 } 1127 writer->setListener(mListener); 1128 mWriter = writer; 1129 return mWriter->start(meta.get()); 1130} 1131 1132status_t StagefrightRecorder::pause() { 1133 LOGV("pause"); 1134 if (mWriter == NULL) { 1135 return UNKNOWN_ERROR; 1136 } 1137 mWriter->pause(); 1138 return OK; 1139} 1140 1141status_t StagefrightRecorder::stop() { 1142 LOGV("stop"); 1143 if (mWriter != NULL) { 1144 mWriter->stop(); 1145 mWriter.clear(); 1146 } 1147 1148 if (mCamera != 0) { 1149 LOGV("Disconnect camera"); 1150 int64_t token = IPCThreadState::self()->clearCallingIdentity(); 1151 if ((mFlags & FLAGS_HOT_CAMERA) == 0) { 1152 LOGV("Camera was cold when we started, stopping preview"); 1153 mCamera->stopPreview(); 1154 } 1155 mCamera->unlock(); 1156 mCamera.clear(); 1157 IPCThreadState::self()->restoreCallingIdentity(token); 1158 mFlags = 0; 1159 } 1160 1161 return OK; 1162} 1163 1164status_t StagefrightRecorder::close() { 1165 LOGV("close"); 1166 stop(); 1167 1168 return OK; 1169} 1170 1171status_t StagefrightRecorder::reset() { 1172 LOGV("reset"); 1173 stop(); 1174 1175 // No audio or video source by default 1176 mAudioSource = AUDIO_SOURCE_LIST_END; 1177 mVideoSource = VIDEO_SOURCE_LIST_END; 1178 1179 // Default parameters 1180 mOutputFormat = OUTPUT_FORMAT_THREE_GPP; 1181 mAudioEncoder = AUDIO_ENCODER_AMR_NB; 1182 mVideoEncoder = VIDEO_ENCODER_H263; 1183 mVideoWidth = 176; 1184 mVideoHeight = 144; 1185 mFrameRate = 20; 1186 mVideoBitRate = 192000; 1187 mSampleRate = 8000; 1188 mAudioChannels = 1; 1189 mAudioBitRate = 12200; 1190 mInterleaveDurationUs = 0; 1191 mIFramesIntervalSec = 1; 1192 mAudioSourceNode = 0; 1193 mUse64BitFileOffset = false; 1194 mMovieTimeScale = 1000; 1195 mAudioTimeScale = 1000; 1196 mVideoTimeScale = 1000; 1197 mCameraId = 0; 1198 mVideoEncoderProfile = -1; 1199 mVideoEncoderLevel = -1; 1200 mMaxFileDurationUs = 0; 1201 mMaxFileSizeBytes = 0; 1202 mTrackEveryTimeDurationUs = 0; 1203 mCaptureTimeLapse = false; 1204 mUseStillCameraForTimeLapse = true; 1205 mTimeBetweenTimeLapseFrameCaptureUs = -1; 1206 mEncoderProfiles = MediaProfiles::getInstance(); 1207 1208 mOutputFd = -1; 1209 mFlags = 0; 1210 1211 return OK; 1212} 1213 1214status_t StagefrightRecorder::getMaxAmplitude(int *max) { 1215 LOGV("getMaxAmplitude"); 1216 1217 if (max == NULL) { 1218 LOGE("Null pointer argument"); 1219 return BAD_VALUE; 1220 } 1221 1222 if (mAudioSourceNode != 0) { 1223 *max = mAudioSourceNode->getMaxAmplitude(); 1224 } else { 1225 *max = 0; 1226 } 1227 1228 return OK; 1229} 1230 1231status_t StagefrightRecorder::dump(int fd, const Vector<String16>& args) const { 1232 const size_t SIZE = 256; 1233 char buffer[SIZE]; 1234 String8 result; 1235 snprintf(buffer, SIZE, " Recorder: %p", this); 1236 snprintf(buffer, SIZE, " Output file (fd %d):\n", mOutputFd); 1237 result.append(buffer); 1238 snprintf(buffer, SIZE, " File format: %d\n", mOutputFormat); 1239 result.append(buffer); 1240 snprintf(buffer, SIZE, " Max file size (bytes): %lld\n", mMaxFileSizeBytes); 1241 result.append(buffer); 1242 snprintf(buffer, SIZE, " Max file duration (us): %lld\n", mMaxFileDurationUs); 1243 result.append(buffer); 1244 snprintf(buffer, SIZE, " File offset length (bits): %d\n", mUse64BitFileOffset? 64: 32); 1245 result.append(buffer); 1246 snprintf(buffer, SIZE, " Interleave duration (us): %d\n", mInterleaveDurationUs); 1247 result.append(buffer); 1248 snprintf(buffer, SIZE, " Progress notification: %lld us\n", mTrackEveryTimeDurationUs); 1249 result.append(buffer); 1250 snprintf(buffer, SIZE, " Audio\n"); 1251 result.append(buffer); 1252 snprintf(buffer, SIZE, " Source: %d\n", mAudioSource); 1253 result.append(buffer); 1254 snprintf(buffer, SIZE, " Encoder: %d\n", mAudioEncoder); 1255 result.append(buffer); 1256 snprintf(buffer, SIZE, " Bit rate (bps): %d\n", mAudioBitRate); 1257 result.append(buffer); 1258 snprintf(buffer, SIZE, " Sampling rate (hz): %d\n", mSampleRate); 1259 result.append(buffer); 1260 snprintf(buffer, SIZE, " Number of channels: %d\n", mAudioChannels); 1261 result.append(buffer); 1262 snprintf(buffer, SIZE, " Max amplitude: %d\n", mAudioSourceNode == 0? 0: mAudioSourceNode->getMaxAmplitude()); 1263 result.append(buffer); 1264 snprintf(buffer, SIZE, " Video\n"); 1265 result.append(buffer); 1266 snprintf(buffer, SIZE, " Source: %d\n", mVideoSource); 1267 result.append(buffer); 1268 snprintf(buffer, SIZE, " Camera Id: %d\n", mCameraId); 1269 result.append(buffer); 1270 snprintf(buffer, SIZE, " Camera flags: %d\n", mFlags); 1271 result.append(buffer); 1272 snprintf(buffer, SIZE, " Encoder: %d\n", mVideoEncoder); 1273 result.append(buffer); 1274 snprintf(buffer, SIZE, " Encoder profile: %d\n", mVideoEncoderProfile); 1275 result.append(buffer); 1276 snprintf(buffer, SIZE, " Encoder level: %d\n", mVideoEncoderLevel); 1277 result.append(buffer); 1278 snprintf(buffer, SIZE, " I frames interval (s): %d\n", mIFramesIntervalSec); 1279 result.append(buffer); 1280 snprintf(buffer, SIZE, " Frame size (pixels): %dx%d\n", mVideoWidth, mVideoHeight); 1281 result.append(buffer); 1282 snprintf(buffer, SIZE, " Frame rate (fps): %d\n", mFrameRate); 1283 result.append(buffer); 1284 snprintf(buffer, SIZE, " Bit rate (bps): %d\n", mVideoBitRate); 1285 result.append(buffer); 1286 ::write(fd, result.string(), result.size()); 1287 return OK; 1288} 1289} // namespace android 1290