StagefrightRecorder.cpp revision 4b79168835965cf0fc41ebe2a367e22b4cb20d08
130ab66297501757d745b9ae10da61adcd891f497Andreas Huber/* 230ab66297501757d745b9ae10da61adcd891f497Andreas Huber * Copyright (C) 2009 The Android Open Source Project 330ab66297501757d745b9ae10da61adcd891f497Andreas Huber * 430ab66297501757d745b9ae10da61adcd891f497Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 530ab66297501757d745b9ae10da61adcd891f497Andreas Huber * you may not use this file except in compliance with the License. 630ab66297501757d745b9ae10da61adcd891f497Andreas Huber * You may obtain a copy of the License at 730ab66297501757d745b9ae10da61adcd891f497Andreas Huber * 830ab66297501757d745b9ae10da61adcd891f497Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 930ab66297501757d745b9ae10da61adcd891f497Andreas Huber * 1030ab66297501757d745b9ae10da61adcd891f497Andreas Huber * Unless required by applicable law or agreed to in writing, software 1130ab66297501757d745b9ae10da61adcd891f497Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 1230ab66297501757d745b9ae10da61adcd891f497Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1330ab66297501757d745b9ae10da61adcd891f497Andreas Huber * See the License for the specific language governing permissions and 1430ab66297501757d745b9ae10da61adcd891f497Andreas Huber * limitations under the License. 1530ab66297501757d745b9ae10da61adcd891f497Andreas Huber */ 1630ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1730ab66297501757d745b9ae10da61adcd891f497Andreas Huber//#define LOG_NDEBUG 0 1830ab66297501757d745b9ae10da61adcd891f497Andreas Huber#define LOG_TAG "StagefrightRecorder" 1930ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include <utils/Log.h> 2030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 2130ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include "StagefrightRecorder.h" 2230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 23c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong#include <binder/IPCThreadState.h> 242dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber#include <media/stagefright/AudioSource.h> 252dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber#include <media/stagefright/AMRWriter.h> 2630ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include <media/stagefright/CameraSource.h> 2765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra#include <media/stagefright/CameraSourceTimeLapse.h> 2830ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include <media/stagefright/MPEG4Writer.h> 2930ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include <media/stagefright/MediaDebug.h> 3030ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include <media/stagefright/MediaDefs.h> 3130ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include <media/stagefright/MetaData.h> 3230ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include <media/stagefright/OMXClient.h> 3330ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include <media/stagefright/OMXCodec.h> 3499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong#include <media/MediaProfiles.h> 353cf613507f1e2f7bd932d921a6e222e426fd3be4Mathias Agopian#include <camera/ICamera.h> 36c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong#include <camera/Camera.h> 37ef9d0cd72e476a4b7556833fb09505a51b626797James Dong#include <camera/CameraParameters.h> 384b79168835965cf0fc41ebe2a367e22b4cb20d08Jamie Gennis#include <surfaceflinger/Surface.h> 3930ab66297501757d745b9ae10da61adcd891f497Andreas Huber#include <utils/Errors.h> 40c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong#include <sys/types.h> 41050b28a593350047845a45a14cc5026221ac1620James Dong#include <ctype.h> 42ca2fa61ef03cac008ea86e6fe16b2e5f9f1a2be3Nipun Kwatra#include <unistd.h> 4330ab66297501757d745b9ae10da61adcd891f497Andreas Huber 4439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber#include "ARTPWriter.h" 4539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 4630ab66297501757d745b9ae10da61adcd891f497Andreas Hubernamespace android { 4730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 48d329e21495eda9dbc531fdd0c26c77f1593ac3f4James DongStagefrightRecorder::StagefrightRecorder() 49d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong : mWriter(NULL), 50d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong mOutputFd(-1) { 51d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong 52d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong LOGV("Constructor"); 5330ab66297501757d745b9ae10da61adcd891f497Andreas Huber reset(); 5430ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 5530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 5630ab66297501757d745b9ae10da61adcd891f497Andreas HuberStagefrightRecorder::~StagefrightRecorder() { 57d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong LOGV("Destructor"); 5830ab66297501757d745b9ae10da61adcd891f497Andreas Huber stop(); 5930ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 6030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 6130ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::init() { 62d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong LOGV("init"); 6330ab66297501757d745b9ae10da61adcd891f497Andreas Huber return OK; 6430ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 6530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 6630ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setAudioSource(audio_source as) { 67d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong LOGV("setAudioSource: %d", as); 68d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong if (as < AUDIO_SOURCE_DEFAULT || 69d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong as >= AUDIO_SOURCE_LIST_END) { 70934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong LOGE("Invalid audio source: %d", as); 71d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong return BAD_VALUE; 72d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong } 73d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong 74d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong if (as == AUDIO_SOURCE_DEFAULT) { 75d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong mAudioSource = AUDIO_SOURCE_MIC; 76d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong } else { 77d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong mAudioSource = as; 78d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong } 7930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 8030ab66297501757d745b9ae10da61adcd891f497Andreas Huber return OK; 8130ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 8230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 8330ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setVideoSource(video_source vs) { 84d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong LOGV("setVideoSource: %d", vs); 85d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong if (vs < VIDEO_SOURCE_DEFAULT || 86d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong vs >= VIDEO_SOURCE_LIST_END) { 87934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong LOGE("Invalid video source: %d", vs); 88d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong return BAD_VALUE; 89d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong } 90d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong 91d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong if (vs == VIDEO_SOURCE_DEFAULT) { 92d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong mVideoSource = VIDEO_SOURCE_CAMERA; 93d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong } else { 94d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong mVideoSource = vs; 95d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong } 9630ab66297501757d745b9ae10da61adcd891f497Andreas Huber 9730ab66297501757d745b9ae10da61adcd891f497Andreas Huber return OK; 9830ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 9930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 10030ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setOutputFormat(output_format of) { 101d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong LOGV("setOutputFormat: %d", of); 102d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong if (of < OUTPUT_FORMAT_DEFAULT || 103d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong of >= OUTPUT_FORMAT_LIST_END) { 104934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong LOGE("Invalid output format: %d", of); 105d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong return BAD_VALUE; 106d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong } 107d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong 108d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong if (of == OUTPUT_FORMAT_DEFAULT) { 109d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong mOutputFormat = OUTPUT_FORMAT_THREE_GPP; 110d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong } else { 111d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong mOutputFormat = of; 112d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong } 11330ab66297501757d745b9ae10da61adcd891f497Andreas Huber 11430ab66297501757d745b9ae10da61adcd891f497Andreas Huber return OK; 11530ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 11630ab66297501757d745b9ae10da61adcd891f497Andreas Huber 11730ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setAudioEncoder(audio_encoder ae) { 118d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong LOGV("setAudioEncoder: %d", ae); 119d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong if (ae < AUDIO_ENCODER_DEFAULT || 120d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong ae >= AUDIO_ENCODER_LIST_END) { 121934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong LOGE("Invalid audio encoder: %d", ae); 122d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong return BAD_VALUE; 123d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong } 124d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong 125d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong if (ae == AUDIO_ENCODER_DEFAULT) { 126d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong mAudioEncoder = AUDIO_ENCODER_AMR_NB; 127d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong } else { 128d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong mAudioEncoder = ae; 129d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong } 13030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 13130ab66297501757d745b9ae10da61adcd891f497Andreas Huber return OK; 13230ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 13330ab66297501757d745b9ae10da61adcd891f497Andreas Huber 13430ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setVideoEncoder(video_encoder ve) { 135d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong LOGV("setVideoEncoder: %d", ve); 136d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong if (ve < VIDEO_ENCODER_DEFAULT || 137d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong ve >= VIDEO_ENCODER_LIST_END) { 138934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong LOGE("Invalid video encoder: %d", ve); 139d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong return BAD_VALUE; 140d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong } 141d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong 142d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong if (ve == VIDEO_ENCODER_DEFAULT) { 143d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong mVideoEncoder = VIDEO_ENCODER_H263; 144d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong } else { 145d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong mVideoEncoder = ve; 146d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong } 14730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 14830ab66297501757d745b9ae10da61adcd891f497Andreas Huber return OK; 14930ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 15030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 15130ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setVideoSize(int width, int height) { 152d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong LOGV("setVideoSize: %dx%d", width, height); 153ef9d0cd72e476a4b7556833fb09505a51b626797James Dong if (width <= 0 || height <= 0) { 154ef9d0cd72e476a4b7556833fb09505a51b626797James Dong LOGE("Invalid video size: %dx%d", width, height); 155ef9d0cd72e476a4b7556833fb09505a51b626797James Dong return BAD_VALUE; 156ef9d0cd72e476a4b7556833fb09505a51b626797James Dong } 157ef9d0cd72e476a4b7556833fb09505a51b626797James Dong 158ef9d0cd72e476a4b7556833fb09505a51b626797James Dong // Additional check on the dimension will be performed later 15930ab66297501757d745b9ae10da61adcd891f497Andreas Huber mVideoWidth = width; 16030ab66297501757d745b9ae10da61adcd891f497Andreas Huber mVideoHeight = height; 16130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 16230ab66297501757d745b9ae10da61adcd891f497Andreas Huber return OK; 16330ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 16430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 16530ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setVideoFrameRate(int frames_per_second) { 166d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong LOGV("setVideoFrameRate: %d", frames_per_second); 167ef9d0cd72e476a4b7556833fb09505a51b626797James Dong if (frames_per_second <= 0 || frames_per_second > 30) { 168ef9d0cd72e476a4b7556833fb09505a51b626797James Dong LOGE("Invalid video frame rate: %d", frames_per_second); 169ef9d0cd72e476a4b7556833fb09505a51b626797James Dong return BAD_VALUE; 170ef9d0cd72e476a4b7556833fb09505a51b626797James Dong } 171ef9d0cd72e476a4b7556833fb09505a51b626797James Dong 172ef9d0cd72e476a4b7556833fb09505a51b626797James Dong // Additional check on the frame rate will be performed later 17330ab66297501757d745b9ae10da61adcd891f497Andreas Huber mFrameRate = frames_per_second; 17430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 17530ab66297501757d745b9ae10da61adcd891f497Andreas Huber return OK; 17630ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 17730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 17830ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) { 1799d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong LOGV("setCamera"); 180c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong if (camera == 0) { 181c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong LOGE("camera is NULL"); 182934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return BAD_VALUE; 183c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong } 184c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong 1859d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong int64_t token = IPCThreadState::self()->clearCallingIdentity(); 1869d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong mFlags &= ~FLAGS_HOT_CAMERA; 187c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong mCamera = Camera::create(camera); 188c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong if (mCamera == 0) { 189c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong LOGE("Unable to connect to camera"); 1909d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong IPCThreadState::self()->restoreCallingIdentity(token); 191934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return -EBUSY; 192c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong } 193c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong 194c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong LOGV("Connected to camera"); 195c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong if (mCamera->previewEnabled()) { 196c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong LOGV("camera is hot"); 197c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong mFlags |= FLAGS_HOT_CAMERA; 198c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong } 1999d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong IPCThreadState::self()->restoreCallingIdentity(token); 20030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 20130ab66297501757d745b9ae10da61adcd891f497Andreas Huber return OK; 20230ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 20330ab66297501757d745b9ae10da61adcd891f497Andreas Huber 2044b79168835965cf0fc41ebe2a367e22b4cb20d08Jamie Gennisstatus_t StagefrightRecorder::setPreviewSurface(const sp<Surface> &surface) { 205d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong LOGV("setPreviewSurface: %p", surface.get()); 20630ab66297501757d745b9ae10da61adcd891f497Andreas Huber mPreviewSurface = surface; 20730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 20830ab66297501757d745b9ae10da61adcd891f497Andreas Huber return OK; 20930ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 21030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 21130ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setOutputFile(const char *path) { 212934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong LOGE("setOutputFile(const char*) must not be called"); 21330ab66297501757d745b9ae10da61adcd891f497Andreas Huber // We don't actually support this at all, as the media_server process 21430ab66297501757d745b9ae10da61adcd891f497Andreas Huber // no longer has permissions to create files. 21530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 216934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return -EPERM; 21730ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 21830ab66297501757d745b9ae10da61adcd891f497Andreas Huber 21930ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t length) { 220d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong LOGV("setOutputFile: %d, %lld, %lld", fd, offset, length); 22130ab66297501757d745b9ae10da61adcd891f497Andreas Huber // These don't make any sense, do they? 22230ab66297501757d745b9ae10da61adcd891f497Andreas Huber CHECK_EQ(offset, 0); 22330ab66297501757d745b9ae10da61adcd891f497Andreas Huber CHECK_EQ(length, 0); 22430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 225934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong if (fd < 0) { 226934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong LOGE("Invalid file descriptor: %d", fd); 227934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return -EBADF; 228934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong } 229934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong 23030ab66297501757d745b9ae10da61adcd891f497Andreas Huber if (mOutputFd >= 0) { 23130ab66297501757d745b9ae10da61adcd891f497Andreas Huber ::close(mOutputFd); 23230ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 23330ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOutputFd = dup(fd); 23430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 23530ab66297501757d745b9ae10da61adcd891f497Andreas Huber return OK; 23630ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 23730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 238050b28a593350047845a45a14cc5026221ac1620James Dong// Attempt to parse an int64 literal optionally surrounded by whitespace, 239050b28a593350047845a45a14cc5026221ac1620James Dong// returns true on success, false otherwise. 240ef9d0cd72e476a4b7556833fb09505a51b626797James Dongstatic bool safe_strtoi64(const char *s, int64_t *val) { 241050b28a593350047845a45a14cc5026221ac1620James Dong char *end; 242ef9d0cd72e476a4b7556833fb09505a51b626797James Dong *val = strtoll(s, &end, 10); 243050b28a593350047845a45a14cc5026221ac1620James Dong 244050b28a593350047845a45a14cc5026221ac1620James Dong if (end == s || errno == ERANGE) { 245050b28a593350047845a45a14cc5026221ac1620James Dong return false; 246050b28a593350047845a45a14cc5026221ac1620James Dong } 247050b28a593350047845a45a14cc5026221ac1620James Dong 248050b28a593350047845a45a14cc5026221ac1620James Dong // Skip trailing whitespace 249050b28a593350047845a45a14cc5026221ac1620James Dong while (isspace(*end)) { 250050b28a593350047845a45a14cc5026221ac1620James Dong ++end; 251050b28a593350047845a45a14cc5026221ac1620James Dong } 252050b28a593350047845a45a14cc5026221ac1620James Dong 253050b28a593350047845a45a14cc5026221ac1620James Dong // For a successful return, the string must contain nothing but a valid 254050b28a593350047845a45a14cc5026221ac1620James Dong // int64 literal optionally surrounded by whitespace. 255050b28a593350047845a45a14cc5026221ac1620James Dong 256050b28a593350047845a45a14cc5026221ac1620James Dong return *end == '\0'; 257050b28a593350047845a45a14cc5026221ac1620James Dong} 258050b28a593350047845a45a14cc5026221ac1620James Dong 259ef9d0cd72e476a4b7556833fb09505a51b626797James Dong// Return true if the value is in [0, 0x007FFFFFFF] 260ef9d0cd72e476a4b7556833fb09505a51b626797James Dongstatic bool safe_strtoi32(const char *s, int32_t *val) { 261ef9d0cd72e476a4b7556833fb09505a51b626797James Dong int64_t temp; 262ef9d0cd72e476a4b7556833fb09505a51b626797James Dong if (safe_strtoi64(s, &temp)) { 263ef9d0cd72e476a4b7556833fb09505a51b626797James Dong if (temp >= 0 && temp <= 0x007FFFFFFF) { 264ef9d0cd72e476a4b7556833fb09505a51b626797James Dong *val = static_cast<int32_t>(temp); 265ef9d0cd72e476a4b7556833fb09505a51b626797James Dong return true; 266ef9d0cd72e476a4b7556833fb09505a51b626797James Dong } 267ef9d0cd72e476a4b7556833fb09505a51b626797James Dong } 268ef9d0cd72e476a4b7556833fb09505a51b626797James Dong return false; 269ef9d0cd72e476a4b7556833fb09505a51b626797James Dong} 270ef9d0cd72e476a4b7556833fb09505a51b626797James Dong 271050b28a593350047845a45a14cc5026221ac1620James Dong// Trim both leading and trailing whitespace from the given string. 272050b28a593350047845a45a14cc5026221ac1620James Dongstatic void TrimString(String8 *s) { 273050b28a593350047845a45a14cc5026221ac1620James Dong size_t num_bytes = s->bytes(); 274050b28a593350047845a45a14cc5026221ac1620James Dong const char *data = s->string(); 275050b28a593350047845a45a14cc5026221ac1620James Dong 276050b28a593350047845a45a14cc5026221ac1620James Dong size_t leading_space = 0; 277050b28a593350047845a45a14cc5026221ac1620James Dong while (leading_space < num_bytes && isspace(data[leading_space])) { 278050b28a593350047845a45a14cc5026221ac1620James Dong ++leading_space; 279050b28a593350047845a45a14cc5026221ac1620James Dong } 280050b28a593350047845a45a14cc5026221ac1620James Dong 281050b28a593350047845a45a14cc5026221ac1620James Dong size_t i = num_bytes; 282050b28a593350047845a45a14cc5026221ac1620James Dong while (i > leading_space && isspace(data[i - 1])) { 283050b28a593350047845a45a14cc5026221ac1620James Dong --i; 284050b28a593350047845a45a14cc5026221ac1620James Dong } 285050b28a593350047845a45a14cc5026221ac1620James Dong 286050b28a593350047845a45a14cc5026221ac1620James Dong s->setTo(String8(&data[leading_space], i - leading_space)); 287050b28a593350047845a45a14cc5026221ac1620James Dong} 288050b28a593350047845a45a14cc5026221ac1620James Dong 289050b28a593350047845a45a14cc5026221ac1620James Dongstatus_t StagefrightRecorder::setParamAudioSamplingRate(int32_t sampleRate) { 290050b28a593350047845a45a14cc5026221ac1620James Dong LOGV("setParamAudioSamplingRate: %d", sampleRate); 291ef9d0cd72e476a4b7556833fb09505a51b626797James Dong if (sampleRate <= 0) { 292ef9d0cd72e476a4b7556833fb09505a51b626797James Dong LOGE("Invalid audio sampling rate: %d", sampleRate); 293ef9d0cd72e476a4b7556833fb09505a51b626797James Dong return BAD_VALUE; 294ef9d0cd72e476a4b7556833fb09505a51b626797James Dong } 295ef9d0cd72e476a4b7556833fb09505a51b626797James Dong 296ef9d0cd72e476a4b7556833fb09505a51b626797James Dong // Additional check on the sample rate will be performed later. 297050b28a593350047845a45a14cc5026221ac1620James Dong mSampleRate = sampleRate; 298050b28a593350047845a45a14cc5026221ac1620James Dong return OK; 299050b28a593350047845a45a14cc5026221ac1620James Dong} 300050b28a593350047845a45a14cc5026221ac1620James Dong 301050b28a593350047845a45a14cc5026221ac1620James Dongstatus_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) { 302050b28a593350047845a45a14cc5026221ac1620James Dong LOGV("setParamAudioNumberOfChannels: %d", channels); 303ef9d0cd72e476a4b7556833fb09505a51b626797James Dong if (channels <= 0 || channels >= 3) { 304ef9d0cd72e476a4b7556833fb09505a51b626797James Dong LOGE("Invalid number of audio channels: %d", channels); 305934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return BAD_VALUE; 306ef9d0cd72e476a4b7556833fb09505a51b626797James Dong } 307ef9d0cd72e476a4b7556833fb09505a51b626797James Dong 308ef9d0cd72e476a4b7556833fb09505a51b626797James Dong // Additional check on the number of channels will be performed later. 309050b28a593350047845a45a14cc5026221ac1620James Dong mAudioChannels = channels; 310050b28a593350047845a45a14cc5026221ac1620James Dong return OK; 311050b28a593350047845a45a14cc5026221ac1620James Dong} 312050b28a593350047845a45a14cc5026221ac1620James Dong 313050b28a593350047845a45a14cc5026221ac1620James Dongstatus_t StagefrightRecorder::setParamAudioEncodingBitRate(int32_t bitRate) { 314050b28a593350047845a45a14cc5026221ac1620James Dong LOGV("setParamAudioEncodingBitRate: %d", bitRate); 315ef9d0cd72e476a4b7556833fb09505a51b626797James Dong if (bitRate <= 0) { 316ef9d0cd72e476a4b7556833fb09505a51b626797James Dong LOGE("Invalid audio encoding bit rate: %d", bitRate); 317ef9d0cd72e476a4b7556833fb09505a51b626797James Dong return BAD_VALUE; 318ef9d0cd72e476a4b7556833fb09505a51b626797James Dong } 319ef9d0cd72e476a4b7556833fb09505a51b626797James Dong 320ef9d0cd72e476a4b7556833fb09505a51b626797James Dong // The target bit rate may not be exactly the same as the requested. 321ef9d0cd72e476a4b7556833fb09505a51b626797James Dong // It depends on many factors, such as rate control, and the bit rate 322ef9d0cd72e476a4b7556833fb09505a51b626797James Dong // range that a specific encoder supports. The mismatch between the 323ef9d0cd72e476a4b7556833fb09505a51b626797James Dong // the target and requested bit rate will NOT be treated as an error. 324050b28a593350047845a45a14cc5026221ac1620James Dong mAudioBitRate = bitRate; 325050b28a593350047845a45a14cc5026221ac1620James Dong return OK; 326050b28a593350047845a45a14cc5026221ac1620James Dong} 327050b28a593350047845a45a14cc5026221ac1620James Dong 328050b28a593350047845a45a14cc5026221ac1620James Dongstatus_t StagefrightRecorder::setParamVideoEncodingBitRate(int32_t bitRate) { 329050b28a593350047845a45a14cc5026221ac1620James Dong LOGV("setParamVideoEncodingBitRate: %d", bitRate); 330ef9d0cd72e476a4b7556833fb09505a51b626797James Dong if (bitRate <= 0) { 331ef9d0cd72e476a4b7556833fb09505a51b626797James Dong LOGE("Invalid video encoding bit rate: %d", bitRate); 332ef9d0cd72e476a4b7556833fb09505a51b626797James Dong return BAD_VALUE; 333ef9d0cd72e476a4b7556833fb09505a51b626797James Dong } 334ef9d0cd72e476a4b7556833fb09505a51b626797James Dong 335ef9d0cd72e476a4b7556833fb09505a51b626797James Dong // The target bit rate may not be exactly the same as the requested. 336ef9d0cd72e476a4b7556833fb09505a51b626797James Dong // It depends on many factors, such as rate control, and the bit rate 337ef9d0cd72e476a4b7556833fb09505a51b626797James Dong // range that a specific encoder supports. The mismatch between the 338ef9d0cd72e476a4b7556833fb09505a51b626797James Dong // the target and requested bit rate will NOT be treated as an error. 339050b28a593350047845a45a14cc5026221ac1620James Dong mVideoBitRate = bitRate; 340050b28a593350047845a45a14cc5026221ac1620James Dong return OK; 341050b28a593350047845a45a14cc5026221ac1620James Dong} 342050b28a593350047845a45a14cc5026221ac1620James Dong 343934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dongstatus_t StagefrightRecorder::setParamMaxFileDurationUs(int64_t timeUs) { 344934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong LOGV("setParamMaxFileDurationUs: %lld us", timeUs); 345e4fc55de48241c5fb4c4b9d652fd2d4cd0b71138James Dong if (timeUs <= 100000LL) { // XXX: 100 milli-seconds 346934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong LOGE("Max file duration is too short: %lld us", timeUs); 347934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return BAD_VALUE; 348ef9d0cd72e476a4b7556833fb09505a51b626797James Dong } 349934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong mMaxFileDurationUs = timeUs; 350934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return OK; 351934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong} 352934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong 353934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dongstatus_t StagefrightRecorder::setParamMaxFileSizeBytes(int64_t bytes) { 354934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong LOGV("setParamMaxFileSizeBytes: %lld bytes", bytes); 355934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong if (bytes <= 1024) { // XXX: 1 kB 356934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong LOGE("Max file size is too small: %lld bytes", bytes); 357934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return BAD_VALUE; 358934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong } 359934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong mMaxFileSizeBytes = bytes; 360050b28a593350047845a45a14cc5026221ac1620James Dong return OK; 361050b28a593350047845a45a14cc5026221ac1620James Dong} 362050b28a593350047845a45a14cc5026221ac1620James Dong 36313aec890216948b0c364f8f92792129d0335f506James Dongstatus_t StagefrightRecorder::setParamInterleaveDuration(int32_t durationUs) { 36413aec890216948b0c364f8f92792129d0335f506James Dong LOGV("setParamInterleaveDuration: %d", durationUs); 365ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong if (durationUs <= 500000) { // 500 ms 366ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong // If interleave duration is too small, it is very inefficient to do 367ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong // interleaving since the metadata overhead will count for a significant 368ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong // portion of the saved contents 369ef9d0cd72e476a4b7556833fb09505a51b626797James Dong LOGE("Audio/video interleave duration is too small: %d us", durationUs); 370ef9d0cd72e476a4b7556833fb09505a51b626797James Dong return BAD_VALUE; 371ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong } else if (durationUs >= 10000000) { // 10 seconds 372ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong // If interleaving duration is too large, it can cause the recording 373ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong // session to use too much memory since we have to save the output 374ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong // data before we write them out 375ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong LOGE("Audio/video interleave duration is too large: %d us", durationUs); 376ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong return BAD_VALUE; 377ef9d0cd72e476a4b7556833fb09505a51b626797James Dong } 37813aec890216948b0c364f8f92792129d0335f506James Dong mInterleaveDurationUs = durationUs; 37913aec890216948b0c364f8f92792129d0335f506James Dong return OK; 38013aec890216948b0c364f8f92792129d0335f506James Dong} 381ef9d0cd72e476a4b7556833fb09505a51b626797James Dong 3828f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong// If seconds < 0, only the first frame is I frame, and rest are all P frames 3838f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong// If seconds == 0, all frames are encoded as I frames. No P frames 3848f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong// If seconds > 0, it is the time spacing (seconds) between 2 neighboring I frames 3858f5f2fcee5c12d08df71d17017410c50951fc2e3James Dongstatus_t StagefrightRecorder::setParamVideoIFramesInterval(int32_t seconds) { 3868f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong LOGV("setParamVideoIFramesInterval: %d seconds", seconds); 3878f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mIFramesIntervalSec = seconds; 388ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong return OK; 389ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong} 390ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong 3912dec2b5be2056c6d9428897dc672185872d30d17James Dongstatus_t StagefrightRecorder::setParam64BitFileOffset(bool use64Bit) { 3922dec2b5be2056c6d9428897dc672185872d30d17James Dong LOGV("setParam64BitFileOffset: %s", 3932dec2b5be2056c6d9428897dc672185872d30d17James Dong use64Bit? "use 64 bit file offset": "use 32 bit file offset"); 3942dec2b5be2056c6d9428897dc672185872d30d17James Dong mUse64BitFileOffset = use64Bit; 3952dec2b5be2056c6d9428897dc672185872d30d17James Dong return OK; 3962dec2b5be2056c6d9428897dc672185872d30d17James Dong} 3972dec2b5be2056c6d9428897dc672185872d30d17James Dong 39893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t StagefrightRecorder::setParamVideoCameraId(int32_t cameraId) { 39993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("setParamVideoCameraId: %d", cameraId); 40093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (cameraId < 0) { 40193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return BAD_VALUE; 40293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 40393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mCameraId = cameraId; 40493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return OK; 40593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 40693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 40793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dongstatus_t StagefrightRecorder::setParamTrackTimeStatus(int64_t timeDurationUs) { 40893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong LOGV("setParamTrackTimeStatus: %lld", timeDurationUs); 40993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (timeDurationUs < 20000) { // Infeasible if shorter than 20 ms? 410934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong LOGE("Tracking time duration too short: %lld us", timeDurationUs); 41193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return BAD_VALUE; 41293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 41393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = timeDurationUs; 41493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return OK; 41593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong} 41693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong 417145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dongstatus_t StagefrightRecorder::setParamVideoEncoderProfile(int32_t profile) { 418145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong LOGV("setParamVideoEncoderProfile: %d", profile); 419145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong 420145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong // Additional check will be done later when we load the encoder. 421145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong // For now, we are accepting values defined in OpenMAX IL. 422145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong mVideoEncoderProfile = profile; 423145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong return OK; 424145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong} 425145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong 426145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dongstatus_t StagefrightRecorder::setParamVideoEncoderLevel(int32_t level) { 427145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong LOGV("setParamVideoEncoderLevel: %d", level); 428145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong 429145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong // Additional check will be done later when we load the encoder. 430145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong // For now, we are accepting values defined in OpenMAX IL. 431145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong mVideoEncoderLevel = level; 432145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong return OK; 433145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong} 434145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong 4358f5f2fcee5c12d08df71d17017410c50951fc2e3James Dongstatus_t StagefrightRecorder::setParamMovieTimeScale(int32_t timeScale) { 4368f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong LOGV("setParamMovieTimeScale: %d", timeScale); 4378f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 4388f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong // The range is set to be the same as the audio's time scale range 4398f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong // since audio's time scale has a wider range. 4408f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (timeScale < 600 || timeScale > 96000) { 4418f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong LOGE("Time scale (%d) for movie is out of range [600, 96000]", timeScale); 4428f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong return BAD_VALUE; 4438f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 4448f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mMovieTimeScale = timeScale; 4458f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong return OK; 4468f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong} 4478f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 4488f5f2fcee5c12d08df71d17017410c50951fc2e3James Dongstatus_t StagefrightRecorder::setParamVideoTimeScale(int32_t timeScale) { 4498f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong LOGV("setParamVideoTimeScale: %d", timeScale); 4508f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 4518f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong // 60000 is chosen to make sure that each video frame from a 60-fps 4528f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong // video has 1000 ticks. 4538f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (timeScale < 600 || timeScale > 60000) { 4548f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong LOGE("Time scale (%d) for video is out of range [600, 60000]", timeScale); 4558f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong return BAD_VALUE; 4568f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 4578f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mVideoTimeScale = timeScale; 4588f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong return OK; 4598f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong} 4608f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 4618f5f2fcee5c12d08df71d17017410c50951fc2e3James Dongstatus_t StagefrightRecorder::setParamAudioTimeScale(int32_t timeScale) { 4628f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong LOGV("setParamAudioTimeScale: %d", timeScale); 4638f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 4648f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong // 96000 Hz is the highest sampling rate support in AAC. 4658f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (timeScale < 600 || timeScale > 96000) { 4668f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong LOGE("Time scale (%d) for audio is out of range [600, 96000]", timeScale); 4678f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong return BAD_VALUE; 4688f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 4698f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mAudioTimeScale = timeScale; 4708f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong return OK; 4718f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong} 4728f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 473e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatrastatus_t StagefrightRecorder::setParamTimeLapseEnable(int32_t timeLapseEnable) { 474e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra LOGV("setParamTimeLapseEnable: %d", timeLapseEnable); 475e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra 476e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra if(timeLapseEnable == 0) { 477e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra mCaptureTimeLapse = false; 478e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra } else if (timeLapseEnable == 1) { 479e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra mCaptureTimeLapse = true; 480e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra } else { 481e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra return BAD_VALUE; 482e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra } 483e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra return OK; 484e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra} 485e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra 486f95ce6452d87316b8f5df6692537bd039377f349Nipun Kwatrastatus_t StagefrightRecorder::setParamUseStillCameraForTimeLapse(int32_t useStillCamera) { 487f95ce6452d87316b8f5df6692537bd039377f349Nipun Kwatra LOGV("setParamUseStillCameraForTimeLapse: %d", useStillCamera); 488f95ce6452d87316b8f5df6692537bd039377f349Nipun Kwatra 489f95ce6452d87316b8f5df6692537bd039377f349Nipun Kwatra if(useStillCamera == 0) { 490f95ce6452d87316b8f5df6692537bd039377f349Nipun Kwatra mUseStillCameraForTimeLapse= false; 491f95ce6452d87316b8f5df6692537bd039377f349Nipun Kwatra } else if (useStillCamera == 1) { 492f95ce6452d87316b8f5df6692537bd039377f349Nipun Kwatra mUseStillCameraForTimeLapse= true; 493f95ce6452d87316b8f5df6692537bd039377f349Nipun Kwatra } else { 494f95ce6452d87316b8f5df6692537bd039377f349Nipun Kwatra return BAD_VALUE; 495f95ce6452d87316b8f5df6692537bd039377f349Nipun Kwatra } 496f95ce6452d87316b8f5df6692537bd039377f349Nipun Kwatra return OK; 497f95ce6452d87316b8f5df6692537bd039377f349Nipun Kwatra} 498f95ce6452d87316b8f5df6692537bd039377f349Nipun Kwatra 499e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatrastatus_t StagefrightRecorder::setParamTimeBetweenTimeLapseFrameCapture(int64_t timeUs) { 500e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra LOGV("setParamTimeBetweenTimeLapseFrameCapture: %lld us", timeUs); 501e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra 502e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra // Not allowing time more than a day 503e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra if (timeUs <= 0 || timeUs > 86400*1E6) { 504e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra LOGE("Time between time lapse frame capture (%lld) is out of range [0, 1 Day]", timeUs); 505e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra return BAD_VALUE; 506e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra } 507e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra 508e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra mTimeBetweenTimeLapseFrameCaptureUs = timeUs; 509e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra return OK; 510e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra} 511e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra 512050b28a593350047845a45a14cc5026221ac1620James Dongstatus_t StagefrightRecorder::setParameter( 513050b28a593350047845a45a14cc5026221ac1620James Dong const String8 &key, const String8 &value) { 514050b28a593350047845a45a14cc5026221ac1620James Dong LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string()); 515050b28a593350047845a45a14cc5026221ac1620James Dong if (key == "max-duration") { 516ef9d0cd72e476a4b7556833fb09505a51b626797James Dong int64_t max_duration_ms; 517050b28a593350047845a45a14cc5026221ac1620James Dong if (safe_strtoi64(value.string(), &max_duration_ms)) { 518934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return setParamMaxFileDurationUs(1000LL * max_duration_ms); 519050b28a593350047845a45a14cc5026221ac1620James Dong } 520050b28a593350047845a45a14cc5026221ac1620James Dong } else if (key == "max-filesize") { 521ef9d0cd72e476a4b7556833fb09505a51b626797James Dong int64_t max_filesize_bytes; 522050b28a593350047845a45a14cc5026221ac1620James Dong if (safe_strtoi64(value.string(), &max_filesize_bytes)) { 523934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return setParamMaxFileSizeBytes(max_filesize_bytes); 524050b28a593350047845a45a14cc5026221ac1620James Dong } 52593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } else if (key == "interleave-duration-us") { 52693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int32_t durationUs; 52793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (safe_strtoi32(value.string(), &durationUs)) { 52893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return setParamInterleaveDuration(durationUs); 52993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 5308f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } else if (key == "param-movie-time-scale") { 5318f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t timeScale; 5328f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (safe_strtoi32(value.string(), &timeScale)) { 5338f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong return setParamMovieTimeScale(timeScale); 5348f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 53593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } else if (key == "param-use-64bit-offset") { 53693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int32_t use64BitOffset; 53793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (safe_strtoi32(value.string(), &use64BitOffset)) { 53893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return setParam64BitFileOffset(use64BitOffset != 0); 53993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 54093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } else if (key == "param-track-time-status") { 54193d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int64_t timeDurationUs; 54293d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (safe_strtoi64(value.string(), &timeDurationUs)) { 54393d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return setParamTrackTimeStatus(timeDurationUs); 54493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 545050b28a593350047845a45a14cc5026221ac1620James Dong } else if (key == "audio-param-sampling-rate") { 546050b28a593350047845a45a14cc5026221ac1620James Dong int32_t sampling_rate; 547ef9d0cd72e476a4b7556833fb09505a51b626797James Dong if (safe_strtoi32(value.string(), &sampling_rate)) { 548050b28a593350047845a45a14cc5026221ac1620James Dong return setParamAudioSamplingRate(sampling_rate); 549050b28a593350047845a45a14cc5026221ac1620James Dong } 550050b28a593350047845a45a14cc5026221ac1620James Dong } else if (key == "audio-param-number-of-channels") { 551050b28a593350047845a45a14cc5026221ac1620James Dong int32_t number_of_channels; 552ef9d0cd72e476a4b7556833fb09505a51b626797James Dong if (safe_strtoi32(value.string(), &number_of_channels)) { 553050b28a593350047845a45a14cc5026221ac1620James Dong return setParamAudioNumberOfChannels(number_of_channels); 554050b28a593350047845a45a14cc5026221ac1620James Dong } 555050b28a593350047845a45a14cc5026221ac1620James Dong } else if (key == "audio-param-encoding-bitrate") { 556050b28a593350047845a45a14cc5026221ac1620James Dong int32_t audio_bitrate; 557ef9d0cd72e476a4b7556833fb09505a51b626797James Dong if (safe_strtoi32(value.string(), &audio_bitrate)) { 558050b28a593350047845a45a14cc5026221ac1620James Dong return setParamAudioEncodingBitRate(audio_bitrate); 559050b28a593350047845a45a14cc5026221ac1620James Dong } 5608f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } else if (key == "audio-param-time-scale") { 5618f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t timeScale; 5628f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (safe_strtoi32(value.string(), &timeScale)) { 5638f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong return setParamAudioTimeScale(timeScale); 5648f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 565050b28a593350047845a45a14cc5026221ac1620James Dong } else if (key == "video-param-encoding-bitrate") { 566050b28a593350047845a45a14cc5026221ac1620James Dong int32_t video_bitrate; 567ef9d0cd72e476a4b7556833fb09505a51b626797James Dong if (safe_strtoi32(value.string(), &video_bitrate)) { 568050b28a593350047845a45a14cc5026221ac1620James Dong return setParamVideoEncodingBitRate(video_bitrate); 569050b28a593350047845a45a14cc5026221ac1620James Dong } 57093d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } else if (key == "video-param-i-frames-interval") { 5718f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t seconds; 5728f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (safe_strtoi32(value.string(), &seconds)) { 5738f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong return setParamVideoIFramesInterval(seconds); 574ddcc4a66d848deef6fb4689e64e30cd9bd2684feJames Dong } 575145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong } else if (key == "video-param-encoder-profile") { 576145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong int32_t profile; 577145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong if (safe_strtoi32(value.string(), &profile)) { 578145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong return setParamVideoEncoderProfile(profile); 579145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong } 580145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong } else if (key == "video-param-encoder-level") { 581145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong int32_t level; 582145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong if (safe_strtoi32(value.string(), &level)) { 583145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong return setParamVideoEncoderLevel(level); 584145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong } 58593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } else if (key == "video-param-camera-id") { 58693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong int32_t cameraId; 58793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (safe_strtoi32(value.string(), &cameraId)) { 58893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong return setParamVideoCameraId(cameraId); 5892dec2b5be2056c6d9428897dc672185872d30d17James Dong } 5908f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } else if (key == "video-param-time-scale") { 5918f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong int32_t timeScale; 5928f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong if (safe_strtoi32(value.string(), &timeScale)) { 5938f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong return setParamVideoTimeScale(timeScale); 5948f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong } 595e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra } else if (key == "time-lapse-enable") { 596e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra int32_t timeLapseEnable; 597e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra if (safe_strtoi32(value.string(), &timeLapseEnable)) { 598e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra return setParamTimeLapseEnable(timeLapseEnable); 599e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra } 600f95ce6452d87316b8f5df6692537bd039377f349Nipun Kwatra } else if (key == "use-still-camera-for-time-lapse") { 601f95ce6452d87316b8f5df6692537bd039377f349Nipun Kwatra int32_t useStillCamera; 602f95ce6452d87316b8f5df6692537bd039377f349Nipun Kwatra if (safe_strtoi32(value.string(), &useStillCamera)) { 603f95ce6452d87316b8f5df6692537bd039377f349Nipun Kwatra return setParamUseStillCameraForTimeLapse(useStillCamera); 604f95ce6452d87316b8f5df6692537bd039377f349Nipun Kwatra } 605e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra } else if (key == "time-between-time-lapse-frame-capture") { 606e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra int64_t timeBetweenTimeLapseFrameCaptureMs; 607e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra if (safe_strtoi64(value.string(), &timeBetweenTimeLapseFrameCaptureMs)) { 608e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra return setParamTimeBetweenTimeLapseFrameCapture( 609e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra 1000LL * timeBetweenTimeLapseFrameCaptureMs); 610e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra } 611050b28a593350047845a45a14cc5026221ac1620James Dong } else { 612050b28a593350047845a45a14cc5026221ac1620James Dong LOGE("setParameter: failed to find key %s", key.string()); 613050b28a593350047845a45a14cc5026221ac1620James Dong } 614ef9d0cd72e476a4b7556833fb09505a51b626797James Dong return BAD_VALUE; 615050b28a593350047845a45a14cc5026221ac1620James Dong} 61630ab66297501757d745b9ae10da61adcd891f497Andreas Huber 617050b28a593350047845a45a14cc5026221ac1620James Dongstatus_t StagefrightRecorder::setParameters(const String8 ¶ms) { 618050b28a593350047845a45a14cc5026221ac1620James Dong LOGV("setParameters: %s", params.string()); 619050b28a593350047845a45a14cc5026221ac1620James Dong const char *cparams = params.string(); 620050b28a593350047845a45a14cc5026221ac1620James Dong const char *key_start = cparams; 621050b28a593350047845a45a14cc5026221ac1620James Dong for (;;) { 622050b28a593350047845a45a14cc5026221ac1620James Dong const char *equal_pos = strchr(key_start, '='); 623050b28a593350047845a45a14cc5026221ac1620James Dong if (equal_pos == NULL) { 624050b28a593350047845a45a14cc5026221ac1620James Dong LOGE("Parameters %s miss a value", cparams); 625050b28a593350047845a45a14cc5026221ac1620James Dong return BAD_VALUE; 626050b28a593350047845a45a14cc5026221ac1620James Dong } 627050b28a593350047845a45a14cc5026221ac1620James Dong String8 key(key_start, equal_pos - key_start); 628050b28a593350047845a45a14cc5026221ac1620James Dong TrimString(&key); 629050b28a593350047845a45a14cc5026221ac1620James Dong if (key.length() == 0) { 630050b28a593350047845a45a14cc5026221ac1620James Dong LOGE("Parameters %s contains an empty key", cparams); 631050b28a593350047845a45a14cc5026221ac1620James Dong return BAD_VALUE; 632050b28a593350047845a45a14cc5026221ac1620James Dong } 633050b28a593350047845a45a14cc5026221ac1620James Dong const char *value_start = equal_pos + 1; 634050b28a593350047845a45a14cc5026221ac1620James Dong const char *semicolon_pos = strchr(value_start, ';'); 635050b28a593350047845a45a14cc5026221ac1620James Dong String8 value; 636050b28a593350047845a45a14cc5026221ac1620James Dong if (semicolon_pos == NULL) { 637050b28a593350047845a45a14cc5026221ac1620James Dong value.setTo(value_start); 638050b28a593350047845a45a14cc5026221ac1620James Dong } else { 639050b28a593350047845a45a14cc5026221ac1620James Dong value.setTo(value_start, semicolon_pos - value_start); 640050b28a593350047845a45a14cc5026221ac1620James Dong } 641050b28a593350047845a45a14cc5026221ac1620James Dong if (setParameter(key, value) != OK) { 642050b28a593350047845a45a14cc5026221ac1620James Dong return BAD_VALUE; 643050b28a593350047845a45a14cc5026221ac1620James Dong } 644050b28a593350047845a45a14cc5026221ac1620James Dong if (semicolon_pos == NULL) { 645050b28a593350047845a45a14cc5026221ac1620James Dong break; // Reaches the end 646050b28a593350047845a45a14cc5026221ac1620James Dong } 647050b28a593350047845a45a14cc5026221ac1620James Dong key_start = semicolon_pos + 1; 648050b28a593350047845a45a14cc5026221ac1620James Dong } 64930ab66297501757d745b9ae10da61adcd891f497Andreas Huber return OK; 65030ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 65130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 65237047fceba836f341d0108beed0991b0f8dfc543James Dongstatus_t StagefrightRecorder::setListener(const sp<IMediaRecorderClient> &listener) { 65330ab66297501757d745b9ae10da61adcd891f497Andreas Huber mListener = listener; 65430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 65530ab66297501757d745b9ae10da61adcd891f497Andreas Huber return OK; 65630ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 65730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 65830ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::prepare() { 65930ab66297501757d745b9ae10da61adcd891f497Andreas Huber return OK; 66030ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 66130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 66230ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::start() { 663934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong CHECK(mOutputFd >= 0); 664934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong 66530ab66297501757d745b9ae10da61adcd891f497Andreas Huber if (mWriter != NULL) { 666934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong LOGE("File writer is not avaialble"); 66730ab66297501757d745b9ae10da61adcd891f497Andreas Huber return UNKNOWN_ERROR; 66830ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 66930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 6702dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber switch (mOutputFormat) { 6712dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber case OUTPUT_FORMAT_DEFAULT: 6722dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber case OUTPUT_FORMAT_THREE_GPP: 6732dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber case OUTPUT_FORMAT_MPEG_4: 6742dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return startMPEG4Recording(); 6752dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 6762dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber case OUTPUT_FORMAT_AMR_NB: 6772dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber case OUTPUT_FORMAT_AMR_WB: 6782dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return startAMRRecording(); 6792dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 680ef9d0cd72e476a4b7556833fb09505a51b626797James Dong case OUTPUT_FORMAT_AAC_ADIF: 681ef9d0cd72e476a4b7556833fb09505a51b626797James Dong case OUTPUT_FORMAT_AAC_ADTS: 682ef9d0cd72e476a4b7556833fb09505a51b626797James Dong return startAACRecording(); 683ef9d0cd72e476a4b7556833fb09505a51b626797James Dong 68439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber case OUTPUT_FORMAT_RTP_AVP: 68539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return startRTPRecording(); 68639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 6872dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber default: 688934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong LOGE("Unsupported output file format: %d", mOutputFormat); 6892dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return UNKNOWN_ERROR; 6902dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber } 6912dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber} 6922dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 693050b28a593350047845a45a14cc5026221ac1620James Dongsp<MediaSource> StagefrightRecorder::createAudioSource() { 6942dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber sp<AudioSource> audioSource = 6952dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber new AudioSource( 6962dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber mAudioSource, 697050b28a593350047845a45a14cc5026221ac1620James Dong mSampleRate, 698be6ec71af2d12e2a55f2f0b1b77d3fa5d593a1c7James Dong mAudioChannels); 6992dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 7002dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber status_t err = audioSource->initCheck(); 7012dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 7022dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber if (err != OK) { 703050b28a593350047845a45a14cc5026221ac1620James Dong LOGE("audio source is not initialized"); 7042dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return NULL; 7052dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber } 7062dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 7072dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber sp<MetaData> encMeta = new MetaData; 708050b28a593350047845a45a14cc5026221ac1620James Dong const char *mime; 709050b28a593350047845a45a14cc5026221ac1620James Dong switch (mAudioEncoder) { 710050b28a593350047845a45a14cc5026221ac1620James Dong case AUDIO_ENCODER_AMR_NB: 711050b28a593350047845a45a14cc5026221ac1620James Dong case AUDIO_ENCODER_DEFAULT: 712050b28a593350047845a45a14cc5026221ac1620James Dong mime = MEDIA_MIMETYPE_AUDIO_AMR_NB; 713050b28a593350047845a45a14cc5026221ac1620James Dong break; 714050b28a593350047845a45a14cc5026221ac1620James Dong case AUDIO_ENCODER_AMR_WB: 715050b28a593350047845a45a14cc5026221ac1620James Dong mime = MEDIA_MIMETYPE_AUDIO_AMR_WB; 716050b28a593350047845a45a14cc5026221ac1620James Dong break; 717050b28a593350047845a45a14cc5026221ac1620James Dong case AUDIO_ENCODER_AAC: 718050b28a593350047845a45a14cc5026221ac1620James Dong mime = MEDIA_MIMETYPE_AUDIO_AAC; 719050b28a593350047845a45a14cc5026221ac1620James Dong break; 720050b28a593350047845a45a14cc5026221ac1620James Dong default: 721050b28a593350047845a45a14cc5026221ac1620James Dong LOGE("Unknown audio encoder: %d", mAudioEncoder); 722050b28a593350047845a45a14cc5026221ac1620James Dong return NULL; 723050b28a593350047845a45a14cc5026221ac1620James Dong } 724050b28a593350047845a45a14cc5026221ac1620James Dong encMeta->setCString(kKeyMIMEType, mime); 7252dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 726b45c62c8e9b05c2703bdae18cc298ae55550db8aAndreas Huber int32_t maxInputSize; 727b45c62c8e9b05c2703bdae18cc298ae55550db8aAndreas Huber CHECK(audioSource->getFormat()->findInt32( 728b45c62c8e9b05c2703bdae18cc298ae55550db8aAndreas Huber kKeyMaxInputSize, &maxInputSize)); 729b45c62c8e9b05c2703bdae18cc298ae55550db8aAndreas Huber 730b45c62c8e9b05c2703bdae18cc298ae55550db8aAndreas Huber encMeta->setInt32(kKeyMaxInputSize, maxInputSize); 731050b28a593350047845a45a14cc5026221ac1620James Dong encMeta->setInt32(kKeyChannelCount, mAudioChannels); 732050b28a593350047845a45a14cc5026221ac1620James Dong encMeta->setInt32(kKeySampleRate, mSampleRate); 733ef9d0cd72e476a4b7556833fb09505a51b626797James Dong encMeta->setInt32(kKeyBitRate, mAudioBitRate); 734c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mAudioTimeScale > 0) { 735c059860c73678a202bfa33062723e8f82fb779d9James Dong encMeta->setInt32(kKeyTimeScale, mAudioTimeScale); 736c059860c73678a202bfa33062723e8f82fb779d9James Dong } 7372dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 7382dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber OMXClient client; 7392dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber CHECK_EQ(client.connect(), OK); 7402dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 7412dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber sp<MediaSource> audioEncoder = 7422dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber OMXCodec::Create(client.interface(), encMeta, 7432dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber true /* createEncoder */, audioSource); 744d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong mAudioSourceNode = audioSource; 7452dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 7462dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return audioEncoder; 7472dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber} 7482dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 749ef9d0cd72e476a4b7556833fb09505a51b626797James Dongstatus_t StagefrightRecorder::startAACRecording() { 750ef9d0cd72e476a4b7556833fb09505a51b626797James Dong CHECK(mOutputFormat == OUTPUT_FORMAT_AAC_ADIF || 751ef9d0cd72e476a4b7556833fb09505a51b626797James Dong mOutputFormat == OUTPUT_FORMAT_AAC_ADTS); 752ef9d0cd72e476a4b7556833fb09505a51b626797James Dong 753ef9d0cd72e476a4b7556833fb09505a51b626797James Dong CHECK(mAudioEncoder == AUDIO_ENCODER_AAC); 754ef9d0cd72e476a4b7556833fb09505a51b626797James Dong CHECK(mAudioSource != AUDIO_SOURCE_LIST_END); 755ef9d0cd72e476a4b7556833fb09505a51b626797James Dong 756ef9d0cd72e476a4b7556833fb09505a51b626797James Dong CHECK(0 == "AACWriter is not implemented yet"); 757ef9d0cd72e476a4b7556833fb09505a51b626797James Dong 758ef9d0cd72e476a4b7556833fb09505a51b626797James Dong return OK; 759ef9d0cd72e476a4b7556833fb09505a51b626797James Dong} 760ef9d0cd72e476a4b7556833fb09505a51b626797James Dong 7612dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huberstatus_t StagefrightRecorder::startAMRRecording() { 762ef9d0cd72e476a4b7556833fb09505a51b626797James Dong CHECK(mOutputFormat == OUTPUT_FORMAT_AMR_NB || 763ef9d0cd72e476a4b7556833fb09505a51b626797James Dong mOutputFormat == OUTPUT_FORMAT_AMR_WB); 764ef9d0cd72e476a4b7556833fb09505a51b626797James Dong 765ef9d0cd72e476a4b7556833fb09505a51b626797James Dong if (mOutputFormat == OUTPUT_FORMAT_AMR_NB) { 766ef9d0cd72e476a4b7556833fb09505a51b626797James Dong if (mAudioEncoder != AUDIO_ENCODER_DEFAULT && 767ef9d0cd72e476a4b7556833fb09505a51b626797James Dong mAudioEncoder != AUDIO_ENCODER_AMR_NB) { 768ef9d0cd72e476a4b7556833fb09505a51b626797James Dong LOGE("Invalid encoder %d used for AMRNB recording", 769ef9d0cd72e476a4b7556833fb09505a51b626797James Dong mAudioEncoder); 770934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return BAD_VALUE; 771ef9d0cd72e476a4b7556833fb09505a51b626797James Dong } 772ef9d0cd72e476a4b7556833fb09505a51b626797James Dong if (mSampleRate != 8000) { 773ef9d0cd72e476a4b7556833fb09505a51b626797James Dong LOGE("Invalid sampling rate %d used for AMRNB recording", 774ef9d0cd72e476a4b7556833fb09505a51b626797James Dong mSampleRate); 775934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return BAD_VALUE; 776ef9d0cd72e476a4b7556833fb09505a51b626797James Dong } 777ef9d0cd72e476a4b7556833fb09505a51b626797James Dong } else { // mOutputFormat must be OUTPUT_FORMAT_AMR_WB 778ef9d0cd72e476a4b7556833fb09505a51b626797James Dong if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) { 779ef9d0cd72e476a4b7556833fb09505a51b626797James Dong LOGE("Invlaid encoder %d used for AMRWB recording", 780ef9d0cd72e476a4b7556833fb09505a51b626797James Dong mAudioEncoder); 781934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return BAD_VALUE; 782ef9d0cd72e476a4b7556833fb09505a51b626797James Dong } 783ef9d0cd72e476a4b7556833fb09505a51b626797James Dong if (mSampleRate != 16000) { 784ef9d0cd72e476a4b7556833fb09505a51b626797James Dong LOGE("Invalid sample rate %d used for AMRWB recording", 785ef9d0cd72e476a4b7556833fb09505a51b626797James Dong mSampleRate); 786934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return BAD_VALUE; 787ef9d0cd72e476a4b7556833fb09505a51b626797James Dong } 788ef9d0cd72e476a4b7556833fb09505a51b626797James Dong } 789ef9d0cd72e476a4b7556833fb09505a51b626797James Dong if (mAudioChannels != 1) { 790ef9d0cd72e476a4b7556833fb09505a51b626797James Dong LOGE("Invalid number of audio channels %d used for amr recording", 791ef9d0cd72e476a4b7556833fb09505a51b626797James Dong mAudioChannels); 792934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return BAD_VALUE; 7932dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber } 7942dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 795ef9d0cd72e476a4b7556833fb09505a51b626797James Dong if (mAudioSource >= AUDIO_SOURCE_LIST_END) { 796ef9d0cd72e476a4b7556833fb09505a51b626797James Dong LOGE("Invalid audio source: %d", mAudioSource); 797934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return BAD_VALUE; 7982dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber } 7992dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 800050b28a593350047845a45a14cc5026221ac1620James Dong sp<MediaSource> audioEncoder = createAudioSource(); 8012dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 8022dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber if (audioEncoder == NULL) { 8032dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return UNKNOWN_ERROR; 8042dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber } 8052dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 8062dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber mWriter = new AMRWriter(dup(mOutputFd)); 8072dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber mWriter->addSource(audioEncoder); 808d599cd4573b5a2d5914c5040e0565ef866749b77James Dong 809d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationUs != 0) { 810d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mWriter->setMaxFileDuration(mMaxFileDurationUs); 811d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 812d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeBytes != 0) { 813d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mWriter->setMaxFileSize(mMaxFileSizeBytes); 814d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 815d599cd4573b5a2d5914c5040e0565ef866749b77James Dong mWriter->setListener(mListener); 8162dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber mWriter->start(); 8172dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 8182dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 8192dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber} 8202dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 82139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huberstatus_t StagefrightRecorder::startRTPRecording() { 82239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_RTP_AVP); 82339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 82439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if ((mAudioSource != AUDIO_SOURCE_LIST_END 82539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber && mVideoSource != VIDEO_SOURCE_LIST_END) 82639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber || (mAudioSource == AUDIO_SOURCE_LIST_END 82739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber && mVideoSource == VIDEO_SOURCE_LIST_END)) { 82839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber // Must have exactly one source. 82939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return BAD_VALUE; 83039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 83139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 83239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (mOutputFd < 0) { 83339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return BAD_VALUE; 83439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 83539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 83639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber sp<MediaSource> source; 83739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 83839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (mAudioSource != AUDIO_SOURCE_LIST_END) { 83939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber source = createAudioSource(); 84039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } else { 84139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber status_t err = setupVideoEncoder(&source); 84239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber if (err != OK) { 84339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return err; 84439ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 84539ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber } 84639ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 84739ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber mWriter = new ARTPWriter(dup(mOutputFd)); 84839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber mWriter->addSource(source); 84939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber mWriter->setListener(mListener); 85039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 85139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber return mWriter->start(); 85239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber} 85339ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 85499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dongvoid StagefrightRecorder::clipVideoFrameRate() { 85599c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong LOGV("clipVideoFrameRate: encoder %d", mVideoEncoder); 85699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong int minFrameRate = mEncoderProfiles->getVideoEncoderParamByName( 85799c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong "enc.vid.fps.min", mVideoEncoder); 85899c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong int maxFrameRate = mEncoderProfiles->getVideoEncoderParamByName( 85999c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong "enc.vid.fps.max", mVideoEncoder); 86099c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong if (mFrameRate < minFrameRate) { 86199c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong LOGW("Intended video encoding frame rate (%d fps) is too small" 86299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong " and will be set to (%d fps)", mFrameRate, minFrameRate); 86399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong mFrameRate = minFrameRate; 86499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong } else if (mFrameRate > maxFrameRate) { 86599c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong LOGW("Intended video encoding frame rate (%d fps) is too large" 86699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong " and will be set to (%d fps)", mFrameRate, maxFrameRate); 86799c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong mFrameRate = maxFrameRate; 86899c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong } 86999c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong} 87099c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong 87199c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dongvoid StagefrightRecorder::clipVideoBitRate() { 87299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong LOGV("clipVideoBitRate: encoder %d", mVideoEncoder); 87399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong int minBitRate = mEncoderProfiles->getVideoEncoderParamByName( 87499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong "enc.vid.bps.min", mVideoEncoder); 87599c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong int maxBitRate = mEncoderProfiles->getVideoEncoderParamByName( 87699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong "enc.vid.bps.max", mVideoEncoder); 87799c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong if (mVideoBitRate < minBitRate) { 87899c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong LOGW("Intended video encoding bit rate (%d bps) is too small" 87999c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong " and will be set to (%d bps)", mVideoBitRate, minBitRate); 88099c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong mVideoBitRate = minBitRate; 88199c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong } else if (mVideoBitRate > maxBitRate) { 88299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong LOGW("Intended video encoding bit rate (%d bps) is too large" 88399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong " and will be set to (%d bps)", mVideoBitRate, maxBitRate); 88499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong mVideoBitRate = maxBitRate; 88599c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong } 88699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong} 88799c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong 88899c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dongvoid StagefrightRecorder::clipVideoFrameWidth() { 88999c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong LOGV("clipVideoFrameWidth: encoder %d", mVideoEncoder); 89099c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong int minFrameWidth = mEncoderProfiles->getVideoEncoderParamByName( 89199c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong "enc.vid.width.min", mVideoEncoder); 89299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong int maxFrameWidth = mEncoderProfiles->getVideoEncoderParamByName( 89399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong "enc.vid.width.max", mVideoEncoder); 89499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong if (mVideoWidth < minFrameWidth) { 89599c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong LOGW("Intended video encoding frame width (%d) is too small" 89699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong " and will be set to (%d)", mVideoWidth, minFrameWidth); 89799c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong mVideoWidth = minFrameWidth; 89899c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong } else if (mVideoWidth > maxFrameWidth) { 89999c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong LOGW("Intended video encoding frame width (%d) is too large" 90099c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong " and will be set to (%d)", mVideoWidth, maxFrameWidth); 90199c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong mVideoWidth = maxFrameWidth; 90299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong } 90399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong} 90499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong 905934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dongstatus_t StagefrightRecorder::setupCameraSource() { 906ca2fa61ef03cac008ea86e6fe16b2e5f9f1a2be3Nipun Kwatra if (!mCaptureTimeLapse) { 907e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra // Dont clip for time lapse capture as encoder will have enough 908e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra // time to encode because of slow capture rate of time lapse. 909e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra clipVideoBitRate(); 910e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra clipVideoFrameRate(); 911e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra clipVideoFrameWidth(); 912e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra clipVideoFrameHeight(); 913e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra } 914934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong 915934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong int64_t token = IPCThreadState::self()->clearCallingIdentity(); 916934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong if (mCamera == 0) { 917934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong mCamera = Camera::connect(mCameraId); 918934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong if (mCamera == 0) { 919934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong LOGE("Camera connection could not be established."); 920934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return -EBUSY; 921934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong } 922934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong mFlags &= ~FLAGS_HOT_CAMERA; 923934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong mCamera->lock(); 924934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong } 925934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong 926934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong // Set the actual video recording frame size 927934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong CameraParameters params(mCamera->getParameters()); 928e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra 929ca2fa61ef03cac008ea86e6fe16b2e5f9f1a2be3Nipun Kwatra // dont change the preview size when using still camera for time lapse 930ca2fa61ef03cac008ea86e6fe16b2e5f9f1a2be3Nipun Kwatra // as mVideoWidth, mVideoHeight may correspond to HD resolution not 931ca2fa61ef03cac008ea86e6fe16b2e5f9f1a2be3Nipun Kwatra // supported by the video camera. 932ca2fa61ef03cac008ea86e6fe16b2e5f9f1a2be3Nipun Kwatra if (!(mCaptureTimeLapse && mUseStillCameraForTimeLapse)) { 933e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra params.setPreviewSize(mVideoWidth, mVideoHeight); 934e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra } 935e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra 936934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong params.setPreviewFrameRate(mFrameRate); 937934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong String8 s = params.flatten(); 93848f6ce0e17297c575dcbb25671a7bee80ba13061James Dong if (OK != mCamera->setParameters(s)) { 93948f6ce0e17297c575dcbb25671a7bee80ba13061James Dong LOGE("Could not change settings." 94048f6ce0e17297c575dcbb25671a7bee80ba13061James Dong " Someone else is using camera %d?", mCameraId); 94148f6ce0e17297c575dcbb25671a7bee80ba13061James Dong return -EBUSY; 94248f6ce0e17297c575dcbb25671a7bee80ba13061James Dong } 943934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong CameraParameters newCameraParams(mCamera->getParameters()); 944934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong 945934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong // Check on video frame size 946934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong int frameWidth = 0, frameHeight = 0; 947934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong newCameraParams.getPreviewSize(&frameWidth, &frameHeight); 948ca2fa61ef03cac008ea86e6fe16b2e5f9f1a2be3Nipun Kwatra if (!(mCaptureTimeLapse && mUseStillCameraForTimeLapse) && 949e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra (frameWidth < 0 || frameWidth != mVideoWidth || 950e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra frameHeight < 0 || frameHeight != mVideoHeight)) { 951934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong LOGE("Failed to set the video frame size to %dx%d", 952934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong mVideoWidth, mVideoHeight); 953934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong IPCThreadState::self()->restoreCallingIdentity(token); 954934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return UNKNOWN_ERROR; 955934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong } 956934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong 957934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong // Check on video frame rate 958934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong int frameRate = newCameraParams.getPreviewFrameRate(); 959934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong if (frameRate < 0 || (frameRate - mFrameRate) != 0) { 960934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong LOGE("Failed to set frame rate to %d fps. The actual " 961934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong "frame rate is %d", mFrameRate, frameRate); 962934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong } 963934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong 96448f6ce0e17297c575dcbb25671a7bee80ba13061James Dong // This CHECK is good, since we just passed the lock/unlock 96548f6ce0e17297c575dcbb25671a7bee80ba13061James Dong // check earlier by calling mCamera->setParameters(). 966934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong CHECK_EQ(OK, mCamera->setPreviewDisplay(mPreviewSurface)); 967934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong IPCThreadState::self()->restoreCallingIdentity(token); 968934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return OK; 969934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong} 970934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong 97199c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dongvoid StagefrightRecorder::clipVideoFrameHeight() { 97299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong LOGV("clipVideoFrameHeight: encoder %d", mVideoEncoder); 97399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong int minFrameHeight = mEncoderProfiles->getVideoEncoderParamByName( 97499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong "enc.vid.height.min", mVideoEncoder); 97599c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong int maxFrameHeight = mEncoderProfiles->getVideoEncoderParamByName( 97699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong "enc.vid.height.max", mVideoEncoder); 97799c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong if (mVideoHeight < minFrameHeight) { 97899c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong LOGW("Intended video encoding frame height (%d) is too small" 97999c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong " and will be set to (%d)", mVideoHeight, minFrameHeight); 98099c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong mVideoHeight = minFrameHeight; 98199c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong } else if (mVideoHeight > maxFrameHeight) { 98299c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong LOGW("Intended video encoding frame height (%d) is too large" 98399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong " and will be set to (%d)", mVideoHeight, maxFrameHeight); 98499c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong mVideoHeight = maxFrameHeight; 98599c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong } 98699c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong} 98799c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong 98839ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huberstatus_t StagefrightRecorder::setupVideoEncoder(sp<MediaSource> *source) { 98939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber source->clear(); 99039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 991934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong status_t err = setupCameraSource(); 992934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong if (err != OK) return err; 9932dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 99465e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra sp<CameraSource> cameraSource = (mCaptureTimeLapse) ? 995f95ce6452d87316b8f5df6692537bd039377f349Nipun Kwatra CameraSourceTimeLapse::CreateFromCamera(mCamera, mUseStillCameraForTimeLapse, 996e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra mTimeBetweenTimeLapseFrameCaptureUs, mVideoWidth, mVideoHeight, mFrameRate): 99765e7e6facda89927cb26594b3b65ae81b3235ebcNipun Kwatra CameraSource::CreateFromCamera(mCamera); 998934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong CHECK(cameraSource != NULL); 999050b28a593350047845a45a14cc5026221ac1620James Dong 1000934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong sp<MetaData> enc_meta = new MetaData; 1001934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong enc_meta->setInt32(kKeyBitRate, mVideoBitRate); 1002934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong enc_meta->setInt32(kKeySampleRate, mFrameRate); 1003ef9d0cd72e476a4b7556833fb09505a51b626797James Dong 1004934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong switch (mVideoEncoder) { 1005934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong case VIDEO_ENCODER_H263: 1006934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263); 1007934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong break; 100865ae665befd929efd1a7d1c9addac41c699f04b2James Dong 1009934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong case VIDEO_ENCODER_MPEG_4_SP: 1010934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); 1011934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong break; 101230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1013934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong case VIDEO_ENCODER_H264: 1014934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); 1015934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong break; 101630ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1017934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong default: 1018934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong CHECK(!"Should not be here, unsupported video encoding."); 1019934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong break; 1020934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong } 1021ef9d0cd72e476a4b7556833fb09505a51b626797James Dong 1022934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong sp<MetaData> meta = cameraSource->getFormat(); 102330ab66297501757d745b9ae10da61adcd891f497Andreas Huber 102429a84457aed4c45bc900998b5e11c03023264208James Dong int32_t width, height, stride, sliceHeight, colorFormat; 1025934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong CHECK(meta->findInt32(kKeyWidth, &width)); 1026934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong CHECK(meta->findInt32(kKeyHeight, &height)); 1027934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong CHECK(meta->findInt32(kKeyStride, &stride)); 1028934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong CHECK(meta->findInt32(kKeySliceHeight, &sliceHeight)); 102929a84457aed4c45bc900998b5e11c03023264208James Dong CHECK(meta->findInt32(kKeyColorFormat, &colorFormat)); 103030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1031934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong enc_meta->setInt32(kKeyWidth, width); 1032934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong enc_meta->setInt32(kKeyHeight, height); 10338f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong enc_meta->setInt32(kKeyIFramesInterval, mIFramesIntervalSec); 1034934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong enc_meta->setInt32(kKeyStride, stride); 1035934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong enc_meta->setInt32(kKeySliceHeight, sliceHeight); 103629a84457aed4c45bc900998b5e11c03023264208James Dong enc_meta->setInt32(kKeyColorFormat, colorFormat); 1037c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mVideoTimeScale > 0) { 1038c059860c73678a202bfa33062723e8f82fb779d9James Dong enc_meta->setInt32(kKeyTimeScale, mVideoTimeScale); 1039c059860c73678a202bfa33062723e8f82fb779d9James Dong } 1040145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong if (mVideoEncoderProfile != -1) { 1041145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong enc_meta->setInt32(kKeyVideoProfile, mVideoEncoderProfile); 1042145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong } 1043145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong if (mVideoEncoderLevel != -1) { 1044145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong enc_meta->setInt32(kKeyVideoLevel, mVideoEncoderLevel); 1045145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong } 104630ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1047934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong OMXClient client; 1048934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong CHECK_EQ(client.connect(), OK); 104930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1050e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra // Use software codec for time lapse 10517a42770f47225483a885b168d05e81b6a81189c0Nipun Kwatra uint32_t encoder_flags = (mCaptureTimeLapse) ? OMXCodec::kPreferSoftwareCodecs : 0; 1052934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong sp<MediaSource> encoder = OMXCodec::Create( 1053934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong client.interface(), enc_meta, 10547a42770f47225483a885b168d05e81b6a81189c0Nipun Kwatra true /* createEncoder */, cameraSource, 10557a42770f47225483a885b168d05e81b6a81189c0Nipun Kwatra NULL, encoder_flags); 1056934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong if (encoder == NULL) { 1057934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return UNKNOWN_ERROR; 1058934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong } 105930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 106039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber *source = encoder; 106139ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber 1062934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return OK; 1063934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong} 106430ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1065934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dongstatus_t StagefrightRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) { 1066934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong sp<MediaSource> audioEncoder; 1067934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong switch(mAudioEncoder) { 1068934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong case AUDIO_ENCODER_AMR_NB: 1069934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong case AUDIO_ENCODER_AMR_WB: 1070934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong case AUDIO_ENCODER_AAC: 1071934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong audioEncoder = createAudioSource(); 1072934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong break; 1073934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong default: 1074934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong LOGE("Unsupported audio encoder: %d", mAudioEncoder); 1075934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return UNKNOWN_ERROR; 1076934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong } 107730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1078934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong if (audioEncoder == NULL) { 1079934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return UNKNOWN_ERROR; 1080934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong } 10818f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong 1082934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong writer->addSource(audioEncoder); 1083934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return OK; 1084934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong} 108530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1086934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dongstatus_t StagefrightRecorder::startMPEG4Recording() { 1087934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong int32_t totalBitRate = 0; 1088934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong status_t err = OK; 1089934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong sp<MediaWriter> writer = new MPEG4Writer(dup(mOutputFd)); 109030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1091934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong // Add audio source first if it exists 1092fc20aab463f527ab3b0664986f0381a86b375884Nipun Kwatra if (!mCaptureTimeLapse && (mAudioSource != AUDIO_SOURCE_LIST_END)) { 1093934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong err = setupAudioEncoder(writer); 1094934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong if (err != OK) return err; 1095934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong totalBitRate += mAudioBitRate; 1096934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong } 1097934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong if (mVideoSource == VIDEO_SOURCE_DEFAULT 1098934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong || mVideoSource == VIDEO_SOURCE_CAMERA) { 109939ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber sp<MediaSource> encoder; 110039ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber err = setupVideoEncoder(&encoder); 1101934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong if (err != OK) return err; 110239ddf8e0f18766f7ba1e3246b774aa6ebd93eea8Andreas Huber writer->addSource(encoder); 11032dec2b5be2056c6d9428897dc672185872d30d17James Dong totalBitRate += mVideoBitRate; 110430ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 110530ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1106f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong if (mInterleaveDurationUs > 0) { 1107f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong reinterpret_cast<MPEG4Writer *>(writer.get())-> 1108f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong setInterleaveDuration(mInterleaveDurationUs); 1109f01528f435e6b1f02d118fcd8305a148c27a89f1James Dong } 1110ef9d0cd72e476a4b7556833fb09505a51b626797James Dong 1111d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileDurationUs != 0) { 1112934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong writer->setMaxFileDuration(mMaxFileDurationUs); 1113d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 1114d599cd4573b5a2d5914c5040e0565ef866749b77James Dong if (mMaxFileSizeBytes != 0) { 1115934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong writer->setMaxFileSize(mMaxFileSizeBytes); 1116d599cd4573b5a2d5914c5040e0565ef866749b77James Dong } 11172dec2b5be2056c6d9428897dc672185872d30d17James Dong sp<MetaData> meta = new MetaData; 111893d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong meta->setInt64(kKeyTime, systemTime() / 1000); 111993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong meta->setInt32(kKeyFileType, mOutputFormat); 11202dec2b5be2056c6d9428897dc672185872d30d17James Dong meta->setInt32(kKeyBitRate, totalBitRate); 11212dec2b5be2056c6d9428897dc672185872d30d17James Dong meta->setInt32(kKey64BitFileOffset, mUse64BitFileOffset); 1122c059860c73678a202bfa33062723e8f82fb779d9James Dong if (mMovieTimeScale > 0) { 1123c059860c73678a202bfa33062723e8f82fb779d9James Dong meta->setInt32(kKeyTimeScale, mMovieTimeScale); 1124c059860c73678a202bfa33062723e8f82fb779d9James Dong } 112593d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong if (mTrackEveryTimeDurationUs > 0) { 112693d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong meta->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs); 112793d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong } 1128934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong writer->setListener(mListener); 1129934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong mWriter = writer; 1130934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong return mWriter->start(meta.get()); 113130ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 113230ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1133a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dongstatus_t StagefrightRecorder::pause() { 1134d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong LOGV("pause"); 1135a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong if (mWriter == NULL) { 1136a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return UNKNOWN_ERROR; 1137a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong } 1138a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong mWriter->pause(); 1139a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong return OK; 1140a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong} 1141a7d1a2dd776bf356c228785a94ba8e0ff6a2ec7fJames Dong 114230ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::stop() { 1143d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong LOGV("stop"); 114437187916a486504acaf83bea30147eb5fbf46ae5James Dong status_t err = OK; 1145d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong if (mWriter != NULL) { 114637187916a486504acaf83bea30147eb5fbf46ae5James Dong err = mWriter->stop(); 1147934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong mWriter.clear(); 114830ab66297501757d745b9ae10da61adcd891f497Andreas Huber } 114930ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1150c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong if (mCamera != 0) { 1151d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong LOGV("Disconnect camera"); 11529d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong int64_t token = IPCThreadState::self()->clearCallingIdentity(); 1153c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong if ((mFlags & FLAGS_HOT_CAMERA) == 0) { 1154c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong LOGV("Camera was cold when we started, stopping preview"); 1155c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong mCamera->stopPreview(); 1156c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong } 11579d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong mCamera->unlock(); 1158934da11c4cc598d3dd3b53726c362bcdcc0fd37fJames Dong mCamera.clear(); 11599d7f58a7da8502a4174a17ac49fcba6efa35a457James Dong IPCThreadState::self()->restoreCallingIdentity(token); 1160c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong mFlags = 0; 1161c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong } 1162d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong 116325d83125cee222993673d3ba261ae1186bcad8c2James Dong if (mOutputFd >= 0) { 116425d83125cee222993673d3ba261ae1186bcad8c2James Dong ::close(mOutputFd); 116525d83125cee222993673d3ba261ae1186bcad8c2James Dong mOutputFd = -1; 116625d83125cee222993673d3ba261ae1186bcad8c2James Dong } 116725d83125cee222993673d3ba261ae1186bcad8c2James Dong 116837187916a486504acaf83bea30147eb5fbf46ae5James Dong return err; 1169d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong} 1170d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong 1171d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dongstatus_t StagefrightRecorder::close() { 1172d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong LOGV("close"); 1173d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong stop(); 1174d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong 117530ab66297501757d745b9ae10da61adcd891f497Andreas Huber return OK; 117630ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 117730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 117830ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::reset() { 1179d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong LOGV("reset"); 118030ab66297501757d745b9ae10da61adcd891f497Andreas Huber stop(); 118130ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1182050b28a593350047845a45a14cc5026221ac1620James Dong // No audio or video source by default 118330ab66297501757d745b9ae10da61adcd891f497Andreas Huber mAudioSource = AUDIO_SOURCE_LIST_END; 118430ab66297501757d745b9ae10da61adcd891f497Andreas Huber mVideoSource = VIDEO_SOURCE_LIST_END; 1185050b28a593350047845a45a14cc5026221ac1620James Dong 1186050b28a593350047845a45a14cc5026221ac1620James Dong // Default parameters 1187050b28a593350047845a45a14cc5026221ac1620James Dong mOutputFormat = OUTPUT_FORMAT_THREE_GPP; 1188050b28a593350047845a45a14cc5026221ac1620James Dong mAudioEncoder = AUDIO_ENCODER_AMR_NB; 1189050b28a593350047845a45a14cc5026221ac1620James Dong mVideoEncoder = VIDEO_ENCODER_H263; 1190050b28a593350047845a45a14cc5026221ac1620James Dong mVideoWidth = 176; 1191050b28a593350047845a45a14cc5026221ac1620James Dong mVideoHeight = 144; 1192050b28a593350047845a45a14cc5026221ac1620James Dong mFrameRate = 20; 1193050b28a593350047845a45a14cc5026221ac1620James Dong mVideoBitRate = 192000; 1194050b28a593350047845a45a14cc5026221ac1620James Dong mSampleRate = 8000; 1195050b28a593350047845a45a14cc5026221ac1620James Dong mAudioChannels = 1; 1196050b28a593350047845a45a14cc5026221ac1620James Dong mAudioBitRate = 12200; 1197e136c3bb38e88315bf8797a464ebf2c788296b22James Dong mInterleaveDurationUs = 0; 11988f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong mIFramesIntervalSec = 1; 1199d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong mAudioSourceNode = 0; 12002dec2b5be2056c6d9428897dc672185872d30d17James Dong mUse64BitFileOffset = false; 1201c059860c73678a202bfa33062723e8f82fb779d9James Dong mMovieTimeScale = -1; 1202c059860c73678a202bfa33062723e8f82fb779d9James Dong mAudioTimeScale = -1; 1203c059860c73678a202bfa33062723e8f82fb779d9James Dong mVideoTimeScale = -1; 120493d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mCameraId = 0; 1205145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong mVideoEncoderProfile = -1; 1206145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong mVideoEncoderLevel = -1; 1207145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong mMaxFileDurationUs = 0; 1208145bfe5eb3e08c9689c28f6bf3287a979438b04bJames Dong mMaxFileSizeBytes = 0; 120993d6b102a13afa23bfa80d74c399d93d542e6ad6James Dong mTrackEveryTimeDurationUs = 0; 1210fc20aab463f527ab3b0664986f0381a86b375884Nipun Kwatra mCaptureTimeLapse = false; 1211f95ce6452d87316b8f5df6692537bd039377f349Nipun Kwatra mUseStillCameraForTimeLapse = true; 1212e4e0a6994d39c4a7cba09c5fff442b2dca1df8f8Nipun Kwatra mTimeBetweenTimeLapseFrameCaptureUs = -1; 121399c2a076b4a46762a22bbb4dfbd51d107e0532d9James Dong mEncoderProfiles = MediaProfiles::getInstance(); 1214050b28a593350047845a45a14cc5026221ac1620James Dong 121530ab66297501757d745b9ae10da61adcd891f497Andreas Huber mOutputFd = -1; 1216c32cd79d9ad4aba7d959b5b3be7361b4715e6f18James Dong mFlags = 0; 121730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 121830ab66297501757d745b9ae10da61adcd891f497Andreas Huber return OK; 121930ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 122030ab66297501757d745b9ae10da61adcd891f497Andreas Huber 122130ab66297501757d745b9ae10da61adcd891f497Andreas Huberstatus_t StagefrightRecorder::getMaxAmplitude(int *max) { 1222d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong LOGV("getMaxAmplitude"); 1223d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong 1224d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong if (max == NULL) { 1225d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong LOGE("Null pointer argument"); 1226d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong return BAD_VALUE; 1227d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong } 1228d329e21495eda9dbc531fdd0c26c77f1593ac3f4James Dong 1229d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong if (mAudioSourceNode != 0) { 1230d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong *max = mAudioSourceNode->getMaxAmplitude(); 1231d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong } else { 1232d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong *max = 0; 1233d3d4e5069e1af0437c4f5a7b4ba344bda5b937afJames Dong } 12342dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber 12352dce41ad26cb3e9e15c9e456a84bcf5309548ca0Andreas Huber return OK; 123630ab66297501757d745b9ae10da61adcd891f497Andreas Huber} 123730ab66297501757d745b9ae10da61adcd891f497Andreas Huber 1238b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dongstatus_t StagefrightRecorder::dump(int fd, const Vector<String16>& args) const { 1239b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong const size_t SIZE = 256; 1240b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong char buffer[SIZE]; 1241b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong String8 result; 1242b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " Recorder: %p", this); 1243b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " Output file (fd %d):\n", mOutputFd); 1244b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 1245b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " File format: %d\n", mOutputFormat); 1246b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 1247b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " Max file size (bytes): %lld\n", mMaxFileSizeBytes); 1248b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 1249b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " Max file duration (us): %lld\n", mMaxFileDurationUs); 1250b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 1251b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " File offset length (bits): %d\n", mUse64BitFileOffset? 64: 32); 1252b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 1253b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " Interleave duration (us): %d\n", mInterleaveDurationUs); 1254b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 1255b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " Progress notification: %lld us\n", mTrackEveryTimeDurationUs); 1256b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 1257b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " Audio\n"); 1258b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 1259b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " Source: %d\n", mAudioSource); 1260b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 1261b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " Encoder: %d\n", mAudioEncoder); 1262b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 1263b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " Bit rate (bps): %d\n", mAudioBitRate); 1264b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 1265b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " Sampling rate (hz): %d\n", mSampleRate); 1266b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 1267b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " Number of channels: %d\n", mAudioChannels); 1268b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 1269b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " Max amplitude: %d\n", mAudioSourceNode == 0? 0: mAudioSourceNode->getMaxAmplitude()); 1270b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 1271b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " Video\n"); 1272b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 1273b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " Source: %d\n", mVideoSource); 1274b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 1275b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " Camera Id: %d\n", mCameraId); 1276b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 1277b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " Camera flags: %d\n", mFlags); 1278b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 1279b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " Encoder: %d\n", mVideoEncoder); 1280b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 1281b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " Encoder profile: %d\n", mVideoEncoderProfile); 1282b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 1283b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " Encoder level: %d\n", mVideoEncoderLevel); 1284b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 12858f5f2fcee5c12d08df71d17017410c50951fc2e3James Dong snprintf(buffer, SIZE, " I frames interval (s): %d\n", mIFramesIntervalSec); 1286b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 1287b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " Frame size (pixels): %dx%d\n", mVideoWidth, mVideoHeight); 1288b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 1289b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " Frame rate (fps): %d\n", mFrameRate); 1290b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 1291b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong snprintf(buffer, SIZE, " Bit rate (bps): %d\n", mVideoBitRate); 1292b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong result.append(buffer); 1293b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong ::write(fd, result.string(), result.size()); 1294b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong return OK; 1295b914122eb9cb54bbeae4ec03bfebb194aecdccbdJames Dong} 129630ab66297501757d745b9ae10da61adcd891f497Andreas Huber} // namespace android 1297