1 /*
2 ** Copyright (c) 2011-2012 The Linux Foundation. All rights reserved.
3 **
4 ** Not a Contribution, Apache license notifications and license are retained
5 ** for attribution purposes only.
6 **
7 ** Licensed under the Apache License, Version 2.0 (the "License");
8 ** you may not use this file except in compliance with the License.
9 ** You may obtain a copy of the License at
10 **
11 ** http://www.apache.org/licenses/LICENSE-2.0
12 **
13 ** Unless required by applicable law or agreed to in writing, software
14 ** distributed under the License is distributed on an "AS IS" BASIS,
15 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 ** See the License for the specific language governing permissions and
17 ** limitations under the License.
18 */
19
20 /*#error uncomment this for compiler test!*/
21
22 //#define ALOG_NDEBUG 0
23 #define ALOG_NIDEBUG 0
24 #define LOG_TAG "QCameraHWI_Record"
25 #include <utils/Log.h>
26 #include <utils/threads.h>
27 #include <cutils/properties.h>
28 #include <fcntl.h>
29 #include <sys/mman.h>
30
31 #include "QCameraStream.h"
32
33
34 #define LIKELY(exp) __builtin_expect(!!(exp), 1)
35 #define UNLIKELY(exp) __builtin_expect(!!(exp), 0)
36
37 /* QCameraStream_record class implementation goes here*/
38 /* following code implement the video streaming capture & encoding logic of this class*/
39 // ---------------------------------------------------------------------------
40 // QCameraStream_record createInstance()
41 // ---------------------------------------------------------------------------
42 namespace android {
43
44
45 // ---------------------------------------------------------------------------
46 // QCameraStream_record Constructor
47 // ---------------------------------------------------------------------------
QCameraStream_record(uint32_t CameraHandle,uint32_t ChannelId,uint32_t Width,uint32_t Height,uint32_t Format,uint8_t NumBuffers,mm_camera_vtbl_t * mm_ops,mm_camera_img_mode imgmode,camera_mode_t mode,QCameraHardwareInterface * camCtrl)48 QCameraStream_record::QCameraStream_record(uint32_t CameraHandle,
49 uint32_t ChannelId,
50 uint32_t Width,
51 uint32_t Height,
52 uint32_t Format,
53 uint8_t NumBuffers,
54 mm_camera_vtbl_t *mm_ops,
55 mm_camera_img_mode imgmode,
56 camera_mode_t mode,
57 QCameraHardwareInterface* camCtrl)
58 // : QCameraStream(cameraId,mode),
59 :QCameraStream(CameraHandle,
60 ChannelId,
61 Width,
62 Height,
63 Format,
64 NumBuffers,
65 mm_ops,
66 imgmode,
67 mode,
68 camCtrl),
69 mDebugFps(false)
70 {
71 char value[PROPERTY_VALUE_MAX];
72 ALOGV("%s: BEGIN", __func__);
73
74 property_get("persist.debug.sf.showfps", value, "0");
75 mDebugFps = atoi(value);
76
77 ALOGV("%s: END", __func__);
78 }
79
80 // ---------------------------------------------------------------------------
81 // QCameraStream_record Destructor
82 // ---------------------------------------------------------------------------
~QCameraStream_record()83 QCameraStream_record::~QCameraStream_record() {
84 ALOGV("%s: BEGIN", __func__);
85 release();
86 ALOGV("%s: END", __func__);
87 }
88
putBuf(uint8_t num_bufs,mm_camera_buf_def_t * bufs)89 int QCameraStream_record::putBuf(uint8_t num_bufs, mm_camera_buf_def_t *bufs)
90 {
91 for(int cnt = 0; cnt < mHalCamCtrl->mRecordingMemory.buffer_count; cnt++) {
92 if (mHalCamCtrl->mStoreMetaDataInFrame) {
93 struct encoder_media_buffer_type * packet =
94 (struct encoder_media_buffer_type *)mHalCamCtrl->mRecordingMemory.metadata_memory[cnt]->data;
95 native_handle_delete(const_cast<native_handle_t *>(packet->meta_handle));
96 mHalCamCtrl->mRecordingMemory.metadata_memory[cnt]->release(
97 mHalCamCtrl->mRecordingMemory.metadata_memory[cnt]);
98 }
99 mHalCamCtrl->mRecordingMemory.camera_memory[cnt]->release(
100 mHalCamCtrl->mRecordingMemory.camera_memory[cnt]);
101
102 #ifdef USE_ION
103 mHalCamCtrl->deallocate_ion_memory(&mHalCamCtrl->mRecordingMemory.mem_info[cnt]);
104 #endif
105 }
106 memset(&mHalCamCtrl->mRecordingMemory, 0, sizeof(mHalCamCtrl->mRecordingMemory));
107 return NO_ERROR;
108 }
109
110 // ---------------------------------------------------------------------------
111 // QCameraStream_record
112 // ---------------------------------------------------------------------------
release()113 void QCameraStream_record::release()
114 {
115 ALOGV("%s: BEGIN", __func__);
116 streamOff(0);
117 deinitStream();
118 ALOGV("%s: END", __func__);
119 }
120
processRecordFrame(mm_camera_super_buf_t * frame)121 status_t QCameraStream_record::processRecordFrame(mm_camera_super_buf_t *frame)
122 {
123 ALOGV("%s : BEGIN",__func__);
124 int video_buf_idx = frame->bufs[0]->buf_idx;
125
126 if(!mActive) {
127 ALOGE("Recording Stopped. Returning callback");
128 return NO_ERROR;
129 }
130
131 if (UNLIKELY(mDebugFps)) {
132 debugShowVideoFPS();
133 }
134 ALOGE("DEBUG4:%d",frame->bufs[0]->stream_id);
135 ALOGE("<DEBUG4>: Timestamp: %ld %ld",frame->bufs[0]->ts.tv_sec,frame->bufs[0]->ts.tv_nsec);
136 mHalCamCtrl->dumpFrameToFile(frame->bufs[0], HAL_DUMP_FRM_VIDEO);
137 camera_data_timestamp_callback rcb = mHalCamCtrl->mDataCbTimestamp;
138 void *rdata = mHalCamCtrl->mCallbackCookie;
139 nsecs_t timeStamp = nsecs_t(frame->bufs[0]->ts.tv_sec)*1000000000LL + \
140 frame->bufs[0]->ts.tv_nsec;
141
142 ALOGE("Send Video frame to services/encoder TimeStamp : %lld",timeStamp);
143 mRecordedFrames[video_buf_idx] = *frame;
144
145 mHalCamCtrl->cache_ops(&mHalCamCtrl->mRecordingMemory.mem_info[video_buf_idx],
146 (void *)mHalCamCtrl->mRecordingMemory.camera_memory[video_buf_idx]->data,
147 ION_IOC_CLEAN_CACHES);
148
149 if (mHalCamCtrl->mStoreMetaDataInFrame) {
150 if((rcb != NULL) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
151 ALOGE("Calling video callback:%d", video_buf_idx);
152 rcb(timeStamp, CAMERA_MSG_VIDEO_FRAME,
153 mHalCamCtrl->mRecordingMemory.metadata_memory[video_buf_idx],
154 0, mHalCamCtrl->mCallbackCookie);
155 }
156 } else {
157 if((rcb != NULL) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
158 ALOGE("Calling video callback2");
159 rcb(timeStamp, CAMERA_MSG_VIDEO_FRAME,
160 mHalCamCtrl->mRecordingMemory.camera_memory[video_buf_idx],
161 0, mHalCamCtrl->mCallbackCookie);
162 }
163 }
164
165 ALOGV("%s : END",__func__);
166 return NO_ERROR;
167 }
168
169 //Record Related Functions
initStream(uint8_t no_cb_needed,uint8_t stream_on)170 status_t QCameraStream_record::initStream(uint8_t no_cb_needed, uint8_t stream_on)
171 {
172 status_t ret = NO_ERROR;
173
174 ALOGI(" %s : E ", __FUNCTION__);
175 mNumBuffers = VIDEO_BUFFER_COUNT;
176 if(mHalCamCtrl->isLowPowerCamcorder()) {
177 ALOGE("%s: lower power camcorder selected", __func__);
178 mNumBuffers = VIDEO_BUFFER_COUNT_LOW_POWER_CAMCORDER;
179 }
180 ret = QCameraStream::initStream(no_cb_needed, stream_on);
181 end:
182 ALOGI(" %s : X ", __FUNCTION__);
183 return ret;
184 }
185
getBuf(mm_camera_frame_len_offset * frame_offset_info,uint8_t num_bufs,uint8_t * initial_reg_flag,mm_camera_buf_def_t * bufs)186 status_t QCameraStream_record::getBuf(mm_camera_frame_len_offset *frame_offset_info,
187 uint8_t num_bufs,
188 uint8_t *initial_reg_flag,
189 mm_camera_buf_def_t *bufs)
190 {
191 ALOGE("%s : BEGIN",__func__);
192
193 if (num_bufs > mNumBuffers) {
194 mNumBuffers = num_bufs;
195 }
196 if ((mNumBuffers == 0) || (mNumBuffers > MM_CAMERA_MAX_NUM_FRAMES)) {
197 ALOGE("%s: Invalid number of buffers (=%d) requested!",
198 __func__, mNumBuffers);
199 return BAD_VALUE;
200 }
201
202 memset(mRecordBuf, 0, sizeof(mRecordBuf));
203 memcpy(&mFrameOffsetInfo, frame_offset_info, sizeof(mFrameOffsetInfo));
204 if (mHalCamCtrl->initHeapMem(&mHalCamCtrl->mRecordingMemory,
205 mNumBuffers,
206 mFrameOffsetInfo.frame_len,
207 MSM_PMEM_VIDEO,
208 &mFrameOffsetInfo,
209 mRecordBuf) < 0) {
210 ALOGE("%s: Error getting heap mem for recording", __func__);
211 return NO_MEMORY;
212 }
213
214 if (mHalCamCtrl->mStoreMetaDataInFrame) {
215 for (int cnt = 0; cnt < mNumBuffers; cnt++) {
216 mHalCamCtrl->mRecordingMemory.metadata_memory[cnt] =
217 mHalCamCtrl->mGetMemory(-1,
218 sizeof(struct encoder_media_buffer_type),
219 1,
220 (void *)this);
221 struct encoder_media_buffer_type * packet =
222 (struct encoder_media_buffer_type *)mHalCamCtrl->mRecordingMemory.metadata_memory[cnt]->data;
223 packet->meta_handle = native_handle_create(1, 2); //1 fd, 1 offset and 1 size
224 packet->buffer_type = kMetadataBufferTypeCameraSource;
225 native_handle_t * nh = const_cast<native_handle_t *>(packet->meta_handle);
226 nh->data[0] = mHalCamCtrl->mRecordingMemory.mem_info[cnt].fd;
227 nh->data[1] = 0;
228 nh->data[2] = mHalCamCtrl->mRecordingMemory.mem_info[cnt].size;
229 }
230 }
231
232 for(int i = 0; i < num_bufs; i++) {
233 bufs[i] = mRecordBuf[i];
234 initial_reg_flag[i] = true;
235 }
236
237 ALOGE("%s : END",__func__);
238 return NO_ERROR;
239 }
240
releaseRecordingFrame(const void * opaque)241 void QCameraStream_record::releaseRecordingFrame(const void *opaque)
242 {
243 ALOGV("%s : BEGIN, opaque = 0x%p",__func__, opaque);
244 if(!mActive)
245 {
246 ALOGE("%s : Recording already stopped!!! Leak???",__func__);
247 return;
248 }
249 for(int cnt = 0; cnt < mHalCamCtrl->mRecordingMemory.buffer_count; cnt++) {
250 if (mHalCamCtrl->mStoreMetaDataInFrame) {
251 if(mHalCamCtrl->mRecordingMemory.metadata_memory[cnt] &&
252 mHalCamCtrl->mRecordingMemory.metadata_memory[cnt]->data == opaque) {
253 /* found the match */
254 ALOGE("Releasing video frames:%d",cnt);
255 if(MM_CAMERA_OK != p_mm_ops->ops->qbuf(mCameraHandle, mChannelId, mRecordedFrames[cnt].bufs[0]))
256 ALOGE("%s : Buf Done Failed",__func__);
257 mHalCamCtrl->cache_ops(&mHalCamCtrl->mRecordingMemory.mem_info[cnt],
258 (void *)mRecordedFrames[cnt].bufs[0]->buffer,
259 ION_IOC_INV_CACHES);
260 ALOGV("%s : END",__func__);
261 return;
262 }
263 } else {
264 if(mHalCamCtrl->mRecordingMemory.camera_memory[cnt] &&
265 mHalCamCtrl->mRecordingMemory.camera_memory[cnt]->data == opaque) {
266 /* found the match */
267 ALOGE("Releasing video frames2");
268 if(MM_CAMERA_OK != p_mm_ops->ops->qbuf(mCameraHandle, mChannelId, mRecordedFrames[cnt].bufs[0]))
269 ALOGE("%s : Buf Done Failed",__func__);
270 mHalCamCtrl->cache_ops(&mHalCamCtrl->mRecordingMemory.mem_info[cnt],
271 (void *)mRecordedFrames[cnt].bufs[0]->buffer,
272 ION_IOC_INV_CACHES);
273 ALOGV("%s : END",__func__);
274 return;
275 }
276 }
277 }
278 ALOGE("%s: cannot find the matched frame with opaue = 0x%p", __func__, opaque);
279 }
280
debugShowVideoFPS() const281 void QCameraStream_record::debugShowVideoFPS() const
282 {
283 static int mFrameCount;
284 static int mLastFrameCount = 0;
285 static nsecs_t mLastFpsTime = 0;
286 static float mFps = 0;
287 mFrameCount++;
288 nsecs_t now = systemTime();
289 nsecs_t diff = now - mLastFpsTime;
290 if (diff > ms2ns(250)) {
291 mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
292 ALOGI("Video Frames Per Second: %.4f", mFps);
293 mLastFpsTime = now;
294 mLastFrameCount = mFrameCount;
295 }
296 }
297
298 }//namespace android
299
300