StagefrightRecorder.cpp revision d599cd4573b5a2d5914c5040e0565ef866749b77
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 <camera/CameraParameters.h> 36#include <surfaceflinger/ISurface.h> 37#include <utils/Errors.h> 38#include <sys/types.h> 39#include <unistd.h> 40#include <ctype.h> 41 42namespace android { 43 44StagefrightRecorder::StagefrightRecorder() { 45 reset(); 46} 47 48StagefrightRecorder::~StagefrightRecorder() { 49 stop(); 50 51 if (mOutputFd >= 0) { 52 ::close(mOutputFd); 53 mOutputFd = -1; 54 } 55} 56 57status_t StagefrightRecorder::init() { 58 return OK; 59} 60 61status_t StagefrightRecorder::setAudioSource(audio_source as) { 62 mAudioSource = as; 63 64 return OK; 65} 66 67status_t StagefrightRecorder::setVideoSource(video_source vs) { 68 mVideoSource = vs; 69 70 return OK; 71} 72 73status_t StagefrightRecorder::setOutputFormat(output_format of) { 74 mOutputFormat = of; 75 76 return OK; 77} 78 79status_t StagefrightRecorder::setAudioEncoder(audio_encoder ae) { 80 mAudioEncoder = ae; 81 82 return OK; 83} 84 85status_t StagefrightRecorder::setVideoEncoder(video_encoder ve) { 86 mVideoEncoder = ve; 87 88 return OK; 89} 90 91status_t StagefrightRecorder::setVideoSize(int width, int height) { 92 if (width <= 0 || height <= 0) { 93 LOGE("Invalid video size: %dx%d", width, height); 94 return BAD_VALUE; 95 } 96 97 // Additional check on the dimension will be performed later 98 mVideoWidth = width; 99 mVideoHeight = height; 100 101 return OK; 102} 103 104status_t StagefrightRecorder::setVideoFrameRate(int frames_per_second) { 105 if (frames_per_second <= 0 || frames_per_second > 30) { 106 LOGE("Invalid video frame rate: %d", frames_per_second); 107 return BAD_VALUE; 108 } 109 110 // Additional check on the frame rate will be performed later 111 mFrameRate = frames_per_second; 112 113 return OK; 114} 115 116status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) { 117 LOGV("setCamera: pid %d pid %d", IPCThreadState::self()->getCallingPid(), getpid()); 118 if (camera == 0) { 119 LOGE("camera is NULL"); 120 return UNKNOWN_ERROR; 121 } 122 123 mFlags &= ~ FLAGS_SET_CAMERA | FLAGS_HOT_CAMERA; 124 mCamera = Camera::create(camera); 125 if (mCamera == 0) { 126 LOGE("Unable to connect to camera"); 127 return UNKNOWN_ERROR; 128 } 129 130 LOGV("Connected to camera"); 131 mFlags |= FLAGS_SET_CAMERA; 132 if (mCamera->previewEnabled()) { 133 LOGV("camera is hot"); 134 mFlags |= FLAGS_HOT_CAMERA; 135 } 136 137 return OK; 138} 139 140status_t StagefrightRecorder::setPreviewSurface(const sp<ISurface> &surface) { 141 mPreviewSurface = surface; 142 143 return OK; 144} 145 146status_t StagefrightRecorder::setOutputFile(const char *path) { 147 // We don't actually support this at all, as the media_server process 148 // no longer has permissions to create files. 149 150 return UNKNOWN_ERROR; 151} 152 153status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t length) { 154 // These don't make any sense, do they? 155 CHECK_EQ(offset, 0); 156 CHECK_EQ(length, 0); 157 158 if (mOutputFd >= 0) { 159 ::close(mOutputFd); 160 } 161 mOutputFd = dup(fd); 162 163 return OK; 164} 165 166// Attempt to parse an int64 literal optionally surrounded by whitespace, 167// returns true on success, false otherwise. 168static bool safe_strtoi64(const char *s, int64_t *val) { 169 char *end; 170 *val = strtoll(s, &end, 10); 171 172 if (end == s || errno == ERANGE) { 173 return false; 174 } 175 176 // Skip trailing whitespace 177 while (isspace(*end)) { 178 ++end; 179 } 180 181 // For a successful return, the string must contain nothing but a valid 182 // int64 literal optionally surrounded by whitespace. 183 184 return *end == '\0'; 185} 186 187// Return true if the value is in [0, 0x007FFFFFFF] 188static bool safe_strtoi32(const char *s, int32_t *val) { 189 int64_t temp; 190 if (safe_strtoi64(s, &temp)) { 191 if (temp >= 0 && temp <= 0x007FFFFFFF) { 192 *val = static_cast<int32_t>(temp); 193 return true; 194 } 195 } 196 return false; 197} 198 199// Trim both leading and trailing whitespace from the given string. 200static void TrimString(String8 *s) { 201 size_t num_bytes = s->bytes(); 202 const char *data = s->string(); 203 204 size_t leading_space = 0; 205 while (leading_space < num_bytes && isspace(data[leading_space])) { 206 ++leading_space; 207 } 208 209 size_t i = num_bytes; 210 while (i > leading_space && isspace(data[i - 1])) { 211 --i; 212 } 213 214 s->setTo(String8(&data[leading_space], i - leading_space)); 215} 216 217status_t StagefrightRecorder::setParamAudioSamplingRate(int32_t sampleRate) { 218 LOGV("setParamAudioSamplingRate: %d", sampleRate); 219 if (sampleRate <= 0) { 220 LOGE("Invalid audio sampling rate: %d", sampleRate); 221 return BAD_VALUE; 222 } 223 224 // Additional check on the sample rate will be performed later. 225 mSampleRate = sampleRate; 226 return OK; 227} 228 229status_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) { 230 LOGV("setParamAudioNumberOfChannels: %d", channels); 231 if (channels <= 0 || channels >= 3) { 232 LOGE("Invalid number of audio channels: %d", channels); 233 } 234 235 // Additional check on the number of channels will be performed later. 236 mAudioChannels = channels; 237 return OK; 238} 239 240status_t StagefrightRecorder::setParamAudioEncodingBitRate(int32_t bitRate) { 241 LOGV("setParamAudioEncodingBitRate: %d", bitRate); 242 if (bitRate <= 0) { 243 LOGE("Invalid audio encoding bit rate: %d", bitRate); 244 return BAD_VALUE; 245 } 246 247 // The target bit rate may not be exactly the same as the requested. 248 // It depends on many factors, such as rate control, and the bit rate 249 // range that a specific encoder supports. The mismatch between the 250 // the target and requested bit rate will NOT be treated as an error. 251 mAudioBitRate = bitRate; 252 return OK; 253} 254 255status_t StagefrightRecorder::setParamVideoEncodingBitRate(int32_t bitRate) { 256 LOGV("setParamVideoEncodingBitRate: %d", bitRate); 257 if (bitRate <= 0) { 258 LOGE("Invalid video encoding bit rate: %d", bitRate); 259 return BAD_VALUE; 260 } 261 262 // The target bit rate may not be exactly the same as the requested. 263 // It depends on many factors, such as rate control, and the bit rate 264 // range that a specific encoder supports. The mismatch between the 265 // the target and requested bit rate will NOT be treated as an error. 266 mVideoBitRate = bitRate; 267 return OK; 268} 269 270status_t StagefrightRecorder::setParamMaxDurationOrFileSize(int64_t limit, 271 bool limit_is_duration) { 272 LOGV("setParamMaxDurationOrFileSize: limit (%d) for %s", 273 limit, limit_is_duration?"duration":"size"); 274 if (limit_is_duration) { // limit is in ms 275 if (limit <= 1000) { // XXX: 1 second 276 LOGE("Max file duration is too short: %lld us", limit); 277 } 278 mMaxFileDurationUs = limit * 1000LL; 279 } else { 280 if (limit <= 1024) { // XXX: 1 kB 281 LOGE("Max file size is too small: %lld bytes", limit); 282 } 283 mMaxFileSizeBytes = limit; 284 } 285 return OK; 286} 287 288status_t StagefrightRecorder::setParamInterleaveDuration(int32_t durationUs) { 289 LOGV("setParamInterleaveDuration: %d", durationUs); 290 if (durationUs <= 20000) { // XXX: 20 ms 291 LOGE("Audio/video interleave duration is too small: %d us", durationUs); 292 return BAD_VALUE; 293 } 294 mInterleaveDurationUs = durationUs; 295 return OK; 296} 297 298status_t StagefrightRecorder::setParameter( 299 const String8 &key, const String8 &value) { 300 LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string()); 301 if (key == "max-duration") { 302 int64_t max_duration_ms; 303 if (safe_strtoi64(value.string(), &max_duration_ms)) { 304 return setParamMaxDurationOrFileSize( 305 max_duration_ms, true /* limit_is_duration */); 306 } 307 } else if (key == "max-filesize") { 308 int64_t max_filesize_bytes; 309 if (safe_strtoi64(value.string(), &max_filesize_bytes)) { 310 return setParamMaxDurationOrFileSize( 311 max_filesize_bytes, false /* limit is filesize */); 312 } 313 } else if (key == "audio-param-sampling-rate") { 314 int32_t sampling_rate; 315 if (safe_strtoi32(value.string(), &sampling_rate)) { 316 return setParamAudioSamplingRate(sampling_rate); 317 } 318 } else if (key == "audio-param-number-of-channels") { 319 int32_t number_of_channels; 320 if (safe_strtoi32(value.string(), &number_of_channels)) { 321 return setParamAudioNumberOfChannels(number_of_channels); 322 } 323 } else if (key == "audio-param-encoding-bitrate") { 324 int32_t audio_bitrate; 325 if (safe_strtoi32(value.string(), &audio_bitrate)) { 326 return setParamAudioEncodingBitRate(audio_bitrate); 327 } 328 } else if (key == "video-param-encoding-bitrate") { 329 int32_t video_bitrate; 330 if (safe_strtoi32(value.string(), &video_bitrate)) { 331 return setParamVideoEncodingBitRate(video_bitrate); 332 } 333 } else if (key == "param-interleave-duration-us") { 334 int32_t durationUs; 335 if (safe_strtoi32(value.string(), &durationUs)) { 336 return setParamInterleaveDuration(durationUs); 337 } 338 } else { 339 LOGE("setParameter: failed to find key %s", key.string()); 340 } 341 return BAD_VALUE; 342} 343 344status_t StagefrightRecorder::setParameters(const String8 ¶ms) { 345 LOGV("setParameters: %s", params.string()); 346 const char *cparams = params.string(); 347 const char *key_start = cparams; 348 for (;;) { 349 const char *equal_pos = strchr(key_start, '='); 350 if (equal_pos == NULL) { 351 LOGE("Parameters %s miss a value", cparams); 352 return BAD_VALUE; 353 } 354 String8 key(key_start, equal_pos - key_start); 355 TrimString(&key); 356 if (key.length() == 0) { 357 LOGE("Parameters %s contains an empty key", cparams); 358 return BAD_VALUE; 359 } 360 const char *value_start = equal_pos + 1; 361 const char *semicolon_pos = strchr(value_start, ';'); 362 String8 value; 363 if (semicolon_pos == NULL) { 364 value.setTo(value_start); 365 } else { 366 value.setTo(value_start, semicolon_pos - value_start); 367 } 368 if (setParameter(key, value) != OK) { 369 return BAD_VALUE; 370 } 371 if (semicolon_pos == NULL) { 372 break; // Reaches the end 373 } 374 key_start = semicolon_pos + 1; 375 } 376 return OK; 377} 378 379status_t StagefrightRecorder::setListener(const sp<IMediaPlayerClient> &listener) { 380 mListener = listener; 381 382 return OK; 383} 384 385status_t StagefrightRecorder::prepare() { 386 return OK; 387} 388 389status_t StagefrightRecorder::start() { 390 if (mWriter != NULL) { 391 return UNKNOWN_ERROR; 392 } 393 394 switch (mOutputFormat) { 395 case OUTPUT_FORMAT_DEFAULT: 396 case OUTPUT_FORMAT_THREE_GPP: 397 case OUTPUT_FORMAT_MPEG_4: 398 return startMPEG4Recording(); 399 400 case OUTPUT_FORMAT_AMR_NB: 401 case OUTPUT_FORMAT_AMR_WB: 402 return startAMRRecording(); 403 404 case OUTPUT_FORMAT_AAC_ADIF: 405 case OUTPUT_FORMAT_AAC_ADTS: 406 return startAACRecording(); 407 408 default: 409 return UNKNOWN_ERROR; 410 } 411} 412 413sp<MediaSource> StagefrightRecorder::createAudioSource() { 414 sp<AudioSource> audioSource = 415 new AudioSource( 416 mAudioSource, 417 mSampleRate, 418 AudioSystem::CHANNEL_IN_MONO); 419 420 status_t err = audioSource->initCheck(); 421 422 if (err != OK) { 423 LOGE("audio source is not initialized"); 424 return NULL; 425 } 426 427 sp<MetaData> encMeta = new MetaData; 428 const char *mime; 429 switch (mAudioEncoder) { 430 case AUDIO_ENCODER_AMR_NB: 431 case AUDIO_ENCODER_DEFAULT: 432 mime = MEDIA_MIMETYPE_AUDIO_AMR_NB; 433 break; 434 case AUDIO_ENCODER_AMR_WB: 435 mime = MEDIA_MIMETYPE_AUDIO_AMR_WB; 436 break; 437 case AUDIO_ENCODER_AAC: 438 mime = MEDIA_MIMETYPE_AUDIO_AAC; 439 break; 440 default: 441 LOGE("Unknown audio encoder: %d", mAudioEncoder); 442 return NULL; 443 } 444 encMeta->setCString(kKeyMIMEType, mime); 445 446 int32_t maxInputSize; 447 CHECK(audioSource->getFormat()->findInt32( 448 kKeyMaxInputSize, &maxInputSize)); 449 450 encMeta->setInt32(kKeyMaxInputSize, maxInputSize); 451 encMeta->setInt32(kKeyChannelCount, mAudioChannels); 452 encMeta->setInt32(kKeySampleRate, mSampleRate); 453 encMeta->setInt32(kKeyBitRate, mAudioBitRate); 454 455 OMXClient client; 456 CHECK_EQ(client.connect(), OK); 457 458 sp<MediaSource> audioEncoder = 459 OMXCodec::Create(client.interface(), encMeta, 460 true /* createEncoder */, audioSource); 461 462 return audioEncoder; 463} 464 465status_t StagefrightRecorder::startAACRecording() { 466 CHECK(mOutputFormat == OUTPUT_FORMAT_AAC_ADIF || 467 mOutputFormat == OUTPUT_FORMAT_AAC_ADTS); 468 469 CHECK(mAudioEncoder == AUDIO_ENCODER_AAC); 470 CHECK(mAudioSource != AUDIO_SOURCE_LIST_END); 471 CHECK(mOutputFd >= 0); 472 473 CHECK(0 == "AACWriter is not implemented yet"); 474 475 return OK; 476} 477 478status_t StagefrightRecorder::startAMRRecording() { 479 CHECK(mOutputFormat == OUTPUT_FORMAT_AMR_NB || 480 mOutputFormat == OUTPUT_FORMAT_AMR_WB); 481 482 if (mOutputFormat == OUTPUT_FORMAT_AMR_NB) { 483 if (mAudioEncoder != AUDIO_ENCODER_DEFAULT && 484 mAudioEncoder != AUDIO_ENCODER_AMR_NB) { 485 LOGE("Invalid encoder %d used for AMRNB recording", 486 mAudioEncoder); 487 return UNKNOWN_ERROR; 488 } 489 if (mSampleRate != 8000) { 490 LOGE("Invalid sampling rate %d used for AMRNB recording", 491 mSampleRate); 492 return UNKNOWN_ERROR; 493 } 494 } else { // mOutputFormat must be OUTPUT_FORMAT_AMR_WB 495 if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) { 496 LOGE("Invlaid encoder %d used for AMRWB recording", 497 mAudioEncoder); 498 return UNKNOWN_ERROR; 499 } 500 if (mSampleRate != 16000) { 501 LOGE("Invalid sample rate %d used for AMRWB recording", 502 mSampleRate); 503 return UNKNOWN_ERROR; 504 } 505 } 506 if (mAudioChannels != 1) { 507 LOGE("Invalid number of audio channels %d used for amr recording", 508 mAudioChannels); 509 return UNKNOWN_ERROR; 510 } 511 512 if (mAudioSource >= AUDIO_SOURCE_LIST_END) { 513 LOGE("Invalid audio source: %d", mAudioSource); 514 return UNKNOWN_ERROR; 515 } 516 517 sp<MediaSource> audioEncoder = createAudioSource(); 518 519 if (audioEncoder == NULL) { 520 return UNKNOWN_ERROR; 521 } 522 523 CHECK(mOutputFd >= 0); 524 mWriter = new AMRWriter(dup(mOutputFd)); 525 mWriter->addSource(audioEncoder); 526 527 if (mMaxFileDurationUs != 0) { 528 mWriter->setMaxFileDuration(mMaxFileDurationUs); 529 } 530 if (mMaxFileSizeBytes != 0) { 531 mWriter->setMaxFileSize(mMaxFileSizeBytes); 532 } 533 mWriter->setListener(mListener); 534 mWriter->start(); 535 536 return OK; 537} 538 539status_t StagefrightRecorder::startMPEG4Recording() { 540 mWriter = new MPEG4Writer(dup(mOutputFd)); 541 542 // Add audio source first if it exists 543 if (mAudioSource != AUDIO_SOURCE_LIST_END) { 544 sp<MediaSource> audioEncoder; 545 switch(mAudioEncoder) { 546 case AUDIO_ENCODER_AMR_NB: 547 case AUDIO_ENCODER_AMR_WB: 548 case AUDIO_ENCODER_AAC: 549 audioEncoder = createAudioSource(); 550 break; 551 default: 552 LOGE("Unsupported audio encoder: %d", mAudioEncoder); 553 return UNKNOWN_ERROR; 554 } 555 556 if (audioEncoder == NULL) { 557 return UNKNOWN_ERROR; 558 } 559 560 mWriter->addSource(audioEncoder); 561 } 562 if (mVideoSource == VIDEO_SOURCE_DEFAULT 563 || mVideoSource == VIDEO_SOURCE_CAMERA) { 564 CHECK(mCamera != NULL); 565 566 if (mCamera == 0) { 567 mCamera = Camera::connect(0); 568 } 569 CHECK(mCamera != NULL); 570 571 // Set the actual video recording frame size 572 CameraParameters params(mCamera->getParameters()); 573 params.setPreviewSize(mVideoWidth, mVideoHeight); 574 params.setPreviewFrameRate(mFrameRate); 575 String8 s = params.flatten(); 576 CHECK_EQ(OK, mCamera->setParameters(s)); 577 CameraParameters newCameraParams(mCamera->getParameters()); 578 579 // Check on video frame size 580 int frameWidth = 0, frameHeight = 0; 581 newCameraParams.getPreviewSize(&frameWidth, &frameHeight); 582 if (frameWidth < 0 || frameWidth != mVideoWidth || 583 frameHeight < 0 || frameHeight != mVideoHeight) { 584 LOGE("Failed to set the video frame size to %dx%d", 585 mVideoWidth, mVideoHeight); 586 return UNKNOWN_ERROR; 587 } 588 589 // Check on video frame rate 590 int frameRate = newCameraParams.getPreviewFrameRate(); 591 if (frameRate < 0 || (frameRate - mFrameRate) != 0) { 592 LOGE("Failed to set frame rate to %d", mFrameRate); 593 return UNKNOWN_ERROR; 594 } 595 596 CHECK_EQ(OK, mCamera->setPreviewDisplay(mPreviewSurface)); 597 598 sp<CameraSource> cameraSource = 599 CameraSource::CreateFromCamera(mCamera); 600 601 CHECK(cameraSource != NULL); 602 603 sp<MetaData> enc_meta = new MetaData; 604 enc_meta->setInt32(kKeyBitRate, mVideoBitRate); 605 enc_meta->setInt32(kKeySampleRate, mFrameRate); // XXX: kKeySampleRate? 606 607 switch (mVideoEncoder) { 608 case VIDEO_ENCODER_H263: 609 enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263); 610 break; 611 612 case VIDEO_ENCODER_MPEG_4_SP: 613 enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); 614 break; 615 616 case VIDEO_ENCODER_H264: 617 enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); 618 break; 619 620 default: 621 CHECK(!"Should not be here, unsupported video encoding."); 622 break; 623 } 624 625 sp<MetaData> meta = cameraSource->getFormat(); 626 627 int32_t width, height; 628 CHECK(meta->findInt32(kKeyWidth, &width)); 629 CHECK(meta->findInt32(kKeyHeight, &height)); 630 631 enc_meta->setInt32(kKeyWidth, width); 632 enc_meta->setInt32(kKeyHeight, height); 633 634 OMXClient client; 635 CHECK_EQ(client.connect(), OK); 636 637 sp<MediaSource> encoder = 638 OMXCodec::Create( 639 client.interface(), enc_meta, 640 true /* createEncoder */, cameraSource); 641 642 CHECK(mOutputFd >= 0); 643 mWriter->addSource(encoder); 644 } 645 646 { 647 // MPEGWriter specific handling 648 MPEG4Writer *writer = ((MPEG4Writer *) mWriter.get()); // mWriter is an MPEGWriter 649 writer->setInterleaveDuration(mInterleaveDurationUs); 650 } 651 652 if (mMaxFileDurationUs != 0) { 653 mWriter->setMaxFileDuration(mMaxFileDurationUs); 654 } 655 if (mMaxFileSizeBytes != 0) { 656 mWriter->setMaxFileSize(mMaxFileSizeBytes); 657 } 658 mWriter->setListener(mListener); 659 mWriter->start(); 660 return OK; 661} 662 663status_t StagefrightRecorder::stop() { 664 if (mWriter == NULL) { 665 return UNKNOWN_ERROR; 666 } 667 668 mWriter->stop(); 669 mWriter = NULL; 670 671 return OK; 672} 673 674status_t StagefrightRecorder::close() { 675 stop(); 676 677 if (mCamera != 0) { 678 if ((mFlags & FLAGS_HOT_CAMERA) == 0) { 679 LOGV("Camera was cold when we started, stopping preview"); 680 mCamera->stopPreview(); 681 } 682 if (mFlags & FLAGS_SET_CAMERA) { 683 LOGV("Unlocking camera"); 684 mCamera->unlock(); 685 } 686 mFlags = 0; 687 } 688 return OK; 689} 690 691status_t StagefrightRecorder::reset() { 692 stop(); 693 694 // No audio or video source by default 695 mAudioSource = AUDIO_SOURCE_LIST_END; 696 mVideoSource = VIDEO_SOURCE_LIST_END; 697 698 // Default parameters 699 mOutputFormat = OUTPUT_FORMAT_THREE_GPP; 700 mAudioEncoder = AUDIO_ENCODER_AMR_NB; 701 mVideoEncoder = VIDEO_ENCODER_H263; 702 mVideoWidth = 176; 703 mVideoHeight = 144; 704 mFrameRate = 20; 705 mVideoBitRate = 192000; 706 mSampleRate = 8000; 707 mAudioChannels = 1; 708 mAudioBitRate = 12200; 709 710 mOutputFd = -1; 711 mFlags = 0; 712 713 return OK; 714} 715 716status_t StagefrightRecorder::getMaxAmplitude(int *max) { 717 *max = 0; 718 719 return OK; 720} 721 722} // namespace android 723