summaryrefslogtreecommitdiff
path: root/tvapi/libtv/tv/ScreenCatch.cpp (plain)
blob: 971ac91ed46f48a503d68ae97b4d4f8fe521273c
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#define LOG_NDEBUG 1
17#define LOG_TAG "ScreenCatch"
18
19#include <media/stagefright/foundation/ADebug.h>
20#include <media/stagefright/MediaDefs.h>
21#include <media/stagefright/MetaData.h>
22#include <OMX_IVCommon.h>
23#include <MetadataBufferType.h>
24
25#include <ui/GraphicBuffer.h>
26#include <gui/ISurfaceComposer.h>
27#include <gui/IGraphicBufferAlloc.h>
28#include <OMX_Component.h>
29
30#include <utils/Log.h>
31#include <utils/String8.h>
32
33#include <private/gui/ComposerService.h>
34
35#include <media/stagefright/ScreenCatch.h>
36#include <media/stagefright/ScreenSource.h>
37
38#include <binder/IPCThreadState.h>
39#include <binder/MemoryBase.h>
40#include <binder/MemoryHeapBase.h>
41
42#include <stdio.h>
43#include <assert.h>
44#include <limits.h>
45#include <unistd.h>
46#include <fcntl.h>
47#include <sched.h>
48#include <sys/types.h>
49#include <sys/stat.h>
50
51#include <binder/IServiceManager.h>
52
53#define BOUNDRY 32
54
55#define ALIGN(x) (x + (BOUNDRY) - 1)& ~((BOUNDRY) - 1)
56
57namespace android {
58
59 struct ScreenCatch::ScreenCatchClient : public BnScreenMediaSourceClient {
60 ScreenCatchClient(void *user)
61 {
62 mUser = user;
63 ALOGE("[%s %d] user:%x", __FUNCTION__, __LINE__, user);
64 }
65
66 virtual void notify(int msg, int ext1, int ext2, const Parcel *obj)
67 {
68 ALOGI("notify %d, %d, %d", msg, ext1, ext2);
69 }
70
71 virtual int dataCallback(const sp<IMemory> &data)
72 {
73 return 0;
74 }
75
76 protected:
77 void *mUser;
78 virtual ~ScreenCatchClient() {}
79
80 private:
81 DISALLOW_EVIL_CONSTRUCTORS(ScreenCatchClient);
82 };
83
84 ScreenCatch::ScreenCatch(uint32_t bufferWidth, uint32_t bufferHeight, uint32_t bitSize) :
85 mWidth(ALIGN(bufferWidth)),
86 mHeight(bufferHeight),
87 mScreenMediaSourceService(NULL),
88 mColorFormat(OMX_COLOR_Format32bitARGB8888),
89 mBitSize(bitSize)
90 {
91 ALOGE("ScreenCatch: %dx%d", bufferWidth, bufferHeight);
92
93 if (bufferWidth <= 0 || bufferHeight <= 0 || bufferWidth > 1920 || bufferHeight > 1080) {
94 ALOGE("Invalid dimensions %dx%d", bufferWidth, bufferHeight);
95 }
96
97 if (bitSize != 24 || bitSize != 32)
98 bitSize = 32;
99
100 mCorpX = -1;
101 mCorpY = -1;
102 mCorpWidth = -1;
103 mCorpHeight = -1;
104
105 }
106
107 ScreenCatch::~ScreenCatch()
108 {
109 ALOGE("~ScreenCatch");
110 }
111
112 void ScreenCatch::setVideoRotation(int degree)
113 {
114 int angle;
115
116 ALOGI("[%s %d] setVideoRotation degree:%x", __FUNCTION__, __LINE__, degree);
117
118 }
119
120 void ScreenCatch::setVideoCrop(int x, int y, int width, int height)
121 {
122 mCorpX = x;
123 mCorpY = y;
124 mCorpWidth = width;
125 mCorpHeight = height;
126 }
127
128 static inline void yuv_to_rgb32(unsigned char y, unsigned char u, unsigned char v, unsigned char *rgb)
129 {
130 register int r, g, b;
131
132 r = (1192 * (y - 16) + 1634 * (v - 128) ) >> 10;
133 g = (1192 * (y - 16) - 833 * (v - 128) - 400 * (u - 128) ) >> 10;
134 b = (1192 * (y - 16) + 2066 * (u - 128) ) >> 10;
135
136 r = r > 255 ? 255 : r < 0 ? 0 : r;
137 g = g > 255 ? 255 : g < 0 ? 0 : g;
138 b = b > 255 ? 255 : b < 0 ? 0 : b;
139
140 /*ARGB*/
141 *rgb = (unsigned char)r;
142 rgb++;
143 *rgb = (unsigned char)g;
144 rgb++;
145 *rgb = (unsigned char)b;
146 rgb++;
147 *rgb = 0xff;
148
149 }
150
151 void nv21_to_rgb32(unsigned char *buf, unsigned char *rgb, int width, int height)
152 {
153 int x, y, z = 0;
154 int h, w;
155 int blocks;
156 unsigned char Y1, Y2, U, V;
157
158 blocks = (width * height) * 2;
159
160 for (h = 0, z = 0; h < height; h += 2) {
161 for (y = 0; y < width * 2; y += 2) {
162
163 Y1 = buf[ h * width + y + 0];
164 V = buf[ blocks / 2 + h * width / 2 + y % width + 0 ];
165 Y2 = buf[ h * width + y + 1];
166 U = buf[ blocks / 2 + h * width / 2 + y % width + 1 ];
167
168 yuv_to_rgb32(Y1, U, V, &rgb[z]);
169 yuv_to_rgb32(Y2, U, V, &rgb[z + 4]);
170 z += 8;
171 }
172 }
173 }
174
175 static inline void yuv_to_rgb24(unsigned char y, unsigned char u, unsigned char v, unsigned char *rgb)
176 {
177 register int r, g, b;
178
179 r = (1192 * (y - 16) + 1634 * (v - 128) ) >> 10;
180 g = (1192 * (y - 16) - 833 * (v - 128) - 400 * (u - 128) ) >> 10;
181 b = (1192 * (y - 16) + 2066 * (u - 128) ) >> 10;
182
183 r = r > 255 ? 255 : r < 0 ? 0 : r;
184 g = g > 255 ? 255 : g < 0 ? 0 : g;
185 b = b > 255 ? 255 : b < 0 ? 0 : b;
186
187 /*ARGB*/
188 *rgb = (unsigned char)r;
189 rgb++;
190 *rgb = (unsigned char)g;
191 rgb++;
192 *rgb = (unsigned char)b;
193 }
194
195 void nv21_to_rgb24(unsigned char *buf, unsigned char *rgb, int width, int height)
196 {
197 int x, y, z = 0;
198 int h, w;
199 int blocks;
200 unsigned char Y1, Y2, U, V;
201
202 blocks = (width * height) * 2;
203
204 for (h = 0, z = 0; h < height; h += 2) {
205 for (y = 0; y < width * 2; y += 2) {
206
207 Y1 = buf[ h * width + y + 0];
208 V = buf[ blocks / 2 + h * width / 2 + y % width + 0 ];
209 Y2 = buf[ h * width + y + 1];
210 U = buf[ blocks / 2 + h * width / 2 + y % width + 1 ];
211
212 yuv_to_rgb24(Y1, U, V, &rgb[z]);
213 yuv_to_rgb24(Y2, U, V, &rgb[z + 3]);
214 z += 6;
215 }
216 }
217 }
218
219 int ScreenCatch::threadFunc()
220 {
221 int64_t pts;
222 int status;
223
224 sp<MemoryHeapBase> newMemoryHeap = new MemoryHeapBase(mWidth * mHeight * 3 / 2);
225 sp<MemoryBase> buffer = new MemoryBase(newMemoryHeap, 0, mWidth * mHeight * 3 / 2);
226
227 ALOGV("[%s %d] empty:%d", __FUNCTION__, __LINE__, mRawBufferQueue.empty());
228
229 while (mStart == true) {
230
231 status = mScreenMediaSourceService->readBuffer(mClientId, buffer, &pts);
232
233 if (status != OK && mStart == true) {
234 usleep(10000);
235 continue;
236 }
237
238 if (mStart != true)
239 break;
240
241 MediaBuffer *accessUnit;
242
243 if (OMX_COLOR_Format24bitRGB888 == mColorFormat) { //rgb 24bit
244 accessUnit = new MediaBuffer(mWidth * mHeight * 3);
245 nv21_to_rgb24((unsigned char *)buffer->pointer(), (unsigned char *)accessUnit->data(), mWidth, mHeight);
246 accessUnit->set_range(0, mWidth * mHeight * 3);
247 } else if (OMX_COLOR_Format32bitARGB8888 == mColorFormat) { //rgba 32bit
248 accessUnit = new MediaBuffer(mWidth * mHeight * 4);
249 nv21_to_rgb32((unsigned char *)buffer->pointer(), (unsigned char *)accessUnit->data(), mWidth, mHeight);
250 accessUnit->set_range(0, mWidth * mHeight * 4);
251 } else if (OMX_COLOR_FormatYUV420SemiPlanar == mColorFormat) { //nv21
252 accessUnit = new MediaBuffer(mWidth * mHeight * 3 / 2);
253 memcpy((unsigned char *)accessUnit->data(), (unsigned char *)buffer->pointer(), mWidth * mHeight * 3 / 2);
254 accessUnit->set_range(0, mWidth * mHeight * 3 / 2);
255 }
256 mRawBufferQueue.push_back(accessUnit);
257 }
258
259 ALOGE("[%s %d] thread out", __FUNCTION__, __LINE__);
260
261 mThreadOutCondition.signal();
262
263 return 0;
264 }
265
266 void *ScreenCatch::ThreadWrapper(void *me)
267 {
268
269 ScreenCatch *Convertor = static_cast<ScreenCatch *>(me);
270 Convertor->threadFunc();
271 return NULL;
272 }
273
274 status_t ScreenCatch::start(MetaData *params)
275 {
276 ALOGE("[%s %d] mWidth:%d mHeight:%d", __FUNCTION__, __LINE__, mWidth, mHeight);
277 Mutex::Autolock autoLock(mLock);
278
279 status_t status;
280 int64_t pts;
281 int client_id;
282
283 sp<IServiceManager> sm = defaultServiceManager();
284 sp<IBinder> binder = sm->getService(String16("media.screenmediasource"));
285 mScreenMediaSourceService = interface_cast<IScreenMediaSource>(binder);
286
287 sp<ScreenCatchClient> mIScreenSourceClient = new ScreenCatchClient(this);
288
289 ALOGE("[%s %d] mWidth:%d mHeight:%d", __FUNCTION__, __LINE__, mWidth, mHeight);
290
291 mScreenMediaSourceService->registerClient(mIScreenSourceClient, mWidth, mHeight, 1, SCREENMEDIASOURC_RAWDATA_TYPE, &client_id, NULL);
292
293 ALOGE("[%s %d] client_id:%d", __FUNCTION__, __LINE__, client_id);
294
295 mClientId = client_id;
296
297 if (status != OK) {
298 ALOGE("setResolutionRatio fail");
299 return !OK;
300 }
301
302 ALOGV("[%s %d] mCorpX:%d mCorpY:%d mCorpWidth:%d mCorpHeight:%d", __FUNCTION__, __LINE__, mCorpX, mCorpY, mCorpWidth, mCorpHeight);
303
304 if (mCorpX != -1)
305 mScreenMediaSourceService->setVideoCrop(client_id, mCorpX, mCorpY, mCorpWidth, mCorpHeight);
306
307
308 status = mScreenMediaSourceService->start(client_id);
309
310 if (status != OK) {
311 mScreenMediaSourceService->unregisterClient(mClientId);
312 ALOGE("ScreenMediaSourceService start fail");
313 return !OK;
314 }
315
316 if (!(params->findInt32(kKeyColorFormat, &mColorFormat)
317 && (mColorFormat != OMX_COLOR_FormatYUV420SemiPlanar
318 || mColorFormat != OMX_COLOR_Format24bitRGB888
319 || mColorFormat != OMX_COLOR_Format32bitARGB8888)))
320 mColorFormat = OMX_COLOR_Format32bitARGB8888;
321
322 pthread_attr_t attr;
323 pthread_attr_init(&attr);
324 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
325 pthread_create(&mThread, &attr, ThreadWrapper, this);
326 pthread_attr_destroy(&attr);
327
328 mStart = true;
329
330 ALOGV("[%s %d]", __FUNCTION__, __LINE__);
331 return OK;
332 }
333
334 status_t ScreenCatch::stop()
335 {
336 ALOGV("[%s %d]", __FUNCTION__, __LINE__);
337 Mutex::Autolock autoLock(mLock);
338 mStart = false;
339
340 mThreadOutCondition.waitRelative(mLock, 1000000000000);
341 ALOGV("[%s %d]", __FUNCTION__, __LINE__);
342
343 while (!mRawBufferQueue.empty()) {
344
345 ALOGV("[%s %d] free buffer", __FUNCTION__, __LINE__);
346
347 MediaBuffer *rawBuffer = *mRawBufferQueue.begin();
348 mRawBufferQueue.erase(mRawBufferQueue.begin());
349 rawBuffer->release();
350 }
351
352 mScreenMediaSourceService->stop(mClientId);
353 mScreenMediaSourceService->unregisterClient(mClientId);
354
355 return OK;
356 }
357
358 status_t ScreenCatch::read(MediaBuffer **buffer)
359 {
360 Mutex::Autolock autoLock(mLock);
361
362 if (!mRawBufferQueue.empty()) {
363 MediaBuffer *rawBuffer = *mRawBufferQueue.begin();
364 mRawBufferQueue.erase(mRawBufferQueue.begin());
365 *buffer = rawBuffer;
366 return OK;
367 }
368
369 return !OK;
370 }
371
372 status_t ScreenCatch::free(MediaBuffer *buffer)
373 {
374 Mutex::Autolock autoLock(mLock);
375 buffer->release();
376 return OK;
377 }
378
379} // end of namespace android
380