[Android N]MediaRecorder系列之StagefrightRecorder录制TS流flow(三)
来源:互联网 发布:广告宣传片制作软件 编辑:程序博客网 时间:2024/05/01 09:00
CameraSource::start
先看CameraSource的start函数:
status_t CameraSource::start(MetaData *meta) { ALOGV("start"); CHECK(!mStarted); if (mInitCheck != OK) { ALOGE("CameraSource is not initialized yet"); return mInitCheck; } char value[PROPERTY_VALUE_MAX]; if (property_get("media.stagefright.record-stats", value, NULL) && (!strcmp(value, "1") || !strcasecmp(value, "true"))) { mCollectStats = true; } mStartTimeUs = 0; mNumInputBuffers = 0; mEncoderFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; mEncoderDataSpace = HAL_DATASPACE_V0_BT709; if (meta) { //这里这个startTimeUs很重要,这里记录了开始录制的时间点,后面打时间戳的时候会用到 int64_t startTimeUs; if (meta->findInt64(kKeyTime, &startTimeUs)) { mStartTimeUs = startTimeUs; } int32_t nBuffers; if (meta->findInt32(kKeyNumBuffers, &nBuffers)) { CHECK_GT(nBuffers, 0); mNumInputBuffers = nBuffers; } // apply encoder color format if specified if (meta->findInt32(kKeyPixelFormat, &mEncoderFormat)) { ALOGI("Using encoder format: %#x", mEncoderFormat); } if (meta->findInt32(kKeyColorSpace, &mEncoderDataSpace)) { ALOGI("Using encoder data space: %#x", mEncoderDataSpace); } } status_t err; //这个才是真正的start的东西。 if ((err = startCameraRecording()) == OK) { mStarted = true; } return err;}
status_t CameraSource::startCameraRecording() { ALOGV("startCameraRecording"); // Reset the identity to the current thread because media server owns the // camera and recording is started by the applications. The applications // will connect to the camera in ICameraRecordingProxy::startRecording. int64_t token = IPCThreadState::self()->clearCallingIdentity(); status_t err; if (mVideoBufferMode == hardware::ICamera::VIDEO_BUFFER_MODE_BUFFER_QUEUE) { // Initialize buffer queue. err = initBufferQueue(mVideoSize.width, mVideoSize.height, mEncoderFormat, (android_dataspace_t)mEncoderDataSpace, mNumInputBuffers > 0 ? mNumInputBuffers : 1); if (err != OK) { ALOGE("%s: Failed to initialize buffer queue: %s (err=%d)", __FUNCTION__, strerror(-err), err); return err; } } else { if (mNumInputBuffers > 0) { err = mCamera->sendCommand( CAMERA_CMD_SET_VIDEO_BUFFER_COUNT, mNumInputBuffers, 0); // This could happen for CameraHAL1 clients; thus the failure is // not a fatal error if (err != OK) { ALOGW("Failed to set video buffer count to %d due to %d", mNumInputBuffers, err); } } //发送CMD去设置camer的参数 err = mCamera->sendCommand( CAMERA_CMD_SET_VIDEO_FORMAT, mEncoderFormat, mEncoderDataSpace); // This could happen for CameraHAL1 clients; thus the failure is // not a fatal error if (err != OK) { ALOGW("Failed to set video encoder format/dataspace to %d, %d due to %d", mEncoderFormat, mEncoderDataSpace, err); } // Create memory heap to store buffers as VideoNativeMetadata. createVideoBufferMemoryHeap(sizeof(VideoNativeHandleMetadata), kDefaultVideoBufferCount); } err = OK; if (mCameraFlags & FLAGS_HOT_CAMERA) { mCamera->unlock(); mCamera.clear(); //让camera开始recorder if ((err = mCameraRecordingProxy->startRecording( new ProxyListener(this))) != OK) { ALOGE("Failed to start recording, received error: %s (%d)", strerror(-err), err); } } else { mCamera->setListener(new CameraSourceListener(this)); mCamera->startRecording(); if (!mCamera->recordingEnabled()) { err = -EINVAL; ALOGE("Failed to start recording"); } } IPCThreadState::self()->restoreCallingIdentity(token); return err;}
再往下就是cameraHAL的部分了,camera的整个框架和结构比较复杂,这里就先直接先跳过,我们就理解成,这个start函数会直接call到cameraHAL,开始进行录制操作,然后我们就等camera喷数据回来。
CameraSourceListener的postDataTimestamp会收到数据抛回来的广播,数据就存在dataPtr
void CameraSourceListener::postDataTimestamp( nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) { sp<CameraSource> source = mSource.promote(); if (source.get() != NULL) { source->dataCallbackTimestamp(timestamp/1000, msgType, dataPtr); }}
source->dataCallbackTimestamp(timestamp/1000, msgType, dataPtr);
就会跑入:
void CameraSource::dataCallbackTimestamp(int64_t timestampUs, int32_t msgType __unused, const sp<IMemory> &data) { ALOGV("dataCallbackTimestamp: timestamp %lld us", (long long)timestampUs); Mutex::Autolock autoLock(mLock); if (shouldSkipFrameLocked(timestampUs)) { releaseOneRecordingFrame(data); return; } //这个flag表示有多少frame已经收到了 ++mNumFramesReceived; CHECK(data != NULL && data->size() > 0); //mFramesReceived这个里面存着camera抓到的一帧,帧数据 mFramesReceived.push_back(data); int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs); //mFrameTimes,打上时间戳 mFrameTimes.push_back(timeUs); ALOGV("initial delay: %" PRId64 ", current time stamp: %" PRId64, mStartTimeUs, timeUs); mFrameAvailableCondition.signal();}
这个mFramesReceived
先记住一下,等下后面read的时候就会用到了。
AudioSource::start
status_t AudioSource::start(MetaData *params) { Mutex::Autolock autoLock(mLock); if (mStarted) { return UNKNOWN_ERROR; } if (mInitCheck != OK) { return NO_INIT; } mTrackMaxAmplitude = false; mMaxAmplitude = 0; mInitialReadTimeUs = 0; mStartTimeUs = 0; int64_t startTimeUs; //mStartTimeUs 记下开始的时间,为后面打算时间戳做准备 if (params && params->findInt64(kKeyTime, &startTimeUs)) { mStartTimeUs = startTimeUs; } //会跑到HAL的start,不跟了 status_t err = mRecord->start(); if (err == OK) { mStarted = true; } else { mRecord.clear(); } return err;}
然后就等数据报回来:
status_t AudioSource::dataCallback(const AudioRecord::Buffer& audioBuffer) { int64_t timeUs = systemTime() / 1000ll; // Estimate the real sampling time of the 1st sample in this buffer // from AudioRecord's latency. (Apply this adjustment first so that // the start time logic is not affected.) timeUs -= mRecord->latency() * 1000LL; ALOGV("dataCallbackTimestamp: %" PRId64 " us", timeUs); Mutex::Autolock autoLock(mLock); if (!mStarted) { ALOGW("Spurious callback from AudioRecord. Drop the audio data."); return OK; } // Drop retrieved and previously lost audio data. if (mNumFramesReceived == 0 && timeUs < mStartTimeUs) { (void) mRecord->getInputFramesLost(); ALOGV("Drop audio data at %" PRId64 "/%" PRId64 " us", timeUs, mStartTimeUs); return OK; } if (mNumFramesReceived == 0 && mPrevSampleTimeUs == 0) { mInitialReadTimeUs = timeUs; // Initial delay if (mStartTimeUs > 0) { mStartTimeUs = timeUs - mStartTimeUs; } else { // Assume latency is constant. mStartTimeUs += mRecord->latency() * 1000; } mPrevSampleTimeUs = mStartTimeUs; } size_t numLostBytes = 0; if (mNumFramesReceived > 0) { // Ignore earlier frame lost // getInputFramesLost() returns the number of lost frames. // Convert number of frames lost to number of bytes lost. numLostBytes = mRecord->getInputFramesLost() * mRecord->frameSize(); } CHECK_EQ(numLostBytes & 1, 0u); CHECK_EQ(audioBuffer.size & 1, 0u); if (numLostBytes > 0) { // Loss of audio frames should happen rarely; thus the LOGW should // not cause a logging spam ALOGW("Lost audio record data: %zu bytes", numLostBytes); } while (numLostBytes > 0) { size_t bufferSize = numLostBytes; if (numLostBytes > kMaxBufferSize) { numLostBytes -= kMaxBufferSize; bufferSize = kMaxBufferSize; } else { numLostBytes = 0; } MediaBuffer *lostAudioBuffer = new MediaBuffer(bufferSize); memset(lostAudioBuffer->data(), 0, bufferSize); lostAudioBuffer->set_range(0, bufferSize); queueInputBuffer_l(lostAudioBuffer, timeUs); } if (audioBuffer.size == 0) { ALOGW("Nothing is available from AudioRecord callback buffer"); return OK; } const size_t bufferSize = audioBuffer.size; MediaBuffer *buffer = new MediaBuffer(bufferSize); memcpy((uint8_t *) buffer->data(), audioBuffer.i16, audioBuffer.size); buffer->set_range(0, bufferSize); //在这个函数中,把buffer装到mBuffersReceived queueInputBuffer_l(buffer, timeUs); return OK;}
mBuffersReceived也记住一个,后面read的时候,就会用到了。
mFramesReceived和mBuffersReceived都是raw data,没有经过encode的数据,encode在后面的read中会再处理。
0 0
- [Android N]MediaRecorder系列之StagefrightRecorder录制TS流flow(三)
- [Android N]MediaRecorder系列之StagefrightRecorder录制TS流flow(一)
- [Android N]MediaRecorder系列之StagefrightRecorder录制TS流flow(二)
- [Android N]MediaRecorder系列之StagefrightRecorder录制TS流flow(四)
- [Android N]MediaRecorder系列之mediaRecorder与StagefrightRecorder
- [Android N]MediaRecorder系列之初识mediaRecorder
- Android之MediaRecorder录制音频
- Android开发之使用MediaRecorder录制声音
- Android开发之使用MediaRecorder录制视频
- Android多媒体之音频、视频录制MediaRecorder
- Android开发之使用MediaRecorder录制视频
- Android开发之使用MediaRecorder录制声音
- Android音频开发之使用MediaRecorder录制
- Android开发之使用MediaRecorder录制声音
- 录制视频之MediaRecorder
- MediaRecorder之音频录制
- MediaRecorder之视频录制
- Android MediaRecorder录制音频
- Linux 设备驱动之 UIO 机制(基本概念)
- Java动态代理机制详解
- babel.html
- android 在fragment中如何监听返回键,home键
- 设计模式原则详解
- [Android N]MediaRecorder系列之StagefrightRecorder录制TS流flow(三)
- 自定义编程移植的加密芯片
- C语言字符串操作
- Android 中关于加载Bitmap知识点
- createjs初学-preloadJS的使用
- java发送post 乱码问题
- C语言再学习 -- 位、字节、字、字长、字元的关系
- 线性表【一】
- BigInteger简单使用及方法总结