+ int left, int top, int right, int bottom)
+{
+ int i, j;
+ int tiled_offset = 0, tiled_offset1 = 0;
+ int linear_offset = 0;
+ int temp1 = 0, temp2 = 0, temp3 = 0, temp4 = 0;
+
+ temp3 = yuv420_width-right;
+ temp1 = temp3-left;
+ /* real width is greater than or equal 256 */
+ if (temp1 >= 256) {
+ for (i = top; i < yuv420_height-bottom; i = i+1) {
+ j = left;
+ temp3 = (j >> 8) << 8;
+ temp3 = temp3 >> 6;
+ temp4 = i >> 5;
+ if (temp4 & 0x1) {
+ /* odd formula: 2 + x + (x >> 2) << 2 + x_block_num * (y - 1) */
+ tiled_offset = temp4 - 1;
+ temp1 = ((yuv420_width + 127) >> 7) << 7;
+ tiled_offset = tiled_offset * (temp1 >> 6);
+ tiled_offset = tiled_offset + temp3;
+ tiled_offset = tiled_offset + 2;
+ temp1 = (temp3 >> 2) << 2;
+ tiled_offset = tiled_offset + temp1;
+ tiled_offset = tiled_offset << 11;
+ tiled_offset1 = tiled_offset + 2048 * 2;
+ temp4 = 8;
+ } else {
+ temp2 = ((yuv420_height+31) >> 5) << 5;
+ if ((i + 32) < temp2) {
+ /* even1 formula: x + ((x + 2) >> 2) << 2 + x_block_num * y */
+ temp1 = temp3 + 2;
+ temp1 = (temp1 >> 2) << 2;
+ tiled_offset = temp3 + temp1;
+ temp1 = ((yuv420_width + 127) >> 7) << 7;
+ tiled_offset = tiled_offset + temp4 * (temp1 >> 6);
+ tiled_offset = tiled_offset << 11;
+ tiled_offset1 = tiled_offset + 2048 * 6;
+ temp4 = 8;
+ } else {
+ /* even2 formula: x + x_block_num * y */
+ temp1 = ((yuv420_width + 127) >> 7) << 7;
+ tiled_offset = temp4 * (temp1 >> 6);
+ tiled_offset = tiled_offset + temp3;
+ tiled_offset = tiled_offset << 11;
+ tiled_offset1 = tiled_offset + 2048 * 2;
+ temp4 = 4;
+ }
+ }
+
+ temp1 = i & 0x1F;
+ tiled_offset = tiled_offset + 64 * temp1;
+ tiled_offset1 = tiled_offset1 + 64 * temp1;
+ temp2 = yuv420_width - left - right;
+ linear_offset = temp2 * (i - top);
+ temp3 = ((j + 256) >> 8) << 8;
+ temp3 = temp3 - j;
+ temp1 = left & 0x3F;
+ if (temp3 > 192) {
+ memcpy(yuv420_dest + linear_offset, nv12t_src + tiled_offset + temp1, 64 - temp1);
+ memcpy(yuv420_dest + linear_offset + 64 - temp1, nv12t_src + tiled_offset + 2048, 64);
+ memcpy(yuv420_dest + linear_offset + 128 - temp1, nv12t_src + tiled_offset1, 64);
+ memcpy(yuv420_dest + linear_offset + 192 - temp1, nv12t_src + tiled_offset1 + 2048, 64);
+ linear_offset = linear_offset + 256 - temp1;
+ } else if (temp3 > 128) {
+ memcpy(yuv420_dest + linear_offset, nv12t_src + tiled_offset + 2048 + temp1, 64 - temp1);
+ memcpy(yuv420_dest + linear_offset + 64 - temp1, nv12t_src + tiled_offset1, 64);
+ memcpy(yuv420_dest + linear_offset + 128 - temp1, nv12t_src + tiled_offset1 + 2048, 64);
+ linear_offset = linear_offset + 192 - temp1;
+ } else if (temp3 > 64) {
+ memcpy(yuv420_dest + linear_offset, nv12t_src + tiled_offset1 + temp1, 64 - temp1);
+ memcpy(yuv420_dest + linear_offset + 64 - temp1, nv12t_src + tiled_offset1 + 2048, 64);
+ linear_offset = linear_offset + 128 - temp1;
+ } else if (temp3 > 0) {
+ memcpy(yuv420_dest + linear_offset, nv12t_src + tiled_offset1 + 2048 + temp1, 64 - temp1);
+ linear_offset = linear_offset + 64 - temp1;
+ }
+
+ tiled_offset = tiled_offset + temp4 * 2048;
+ j = (left >> 8) << 8;
+ j = j + 256;
+ temp2 = yuv420_width - right - 256;
+ for (; j <= temp2; j = j + 256) {
+ memcpy(yuv420_dest + linear_offset, nv12t_src + tiled_offset, 64);
+ tiled_offset1 = tiled_offset1 + temp4 * 2048;
+ memcpy(yuv420_dest + linear_offset + 64, nv12t_src + tiled_offset + 2048, 64);
+ memcpy(yuv420_dest + linear_offset + 128, nv12t_src + tiled_offset1, 64);
+ tiled_offset = tiled_offset + temp4 * 2048;
+ memcpy(yuv420_dest + linear_offset + 192, nv12t_src + tiled_offset1 + 2048, 64);
+ linear_offset = linear_offset + 256;
+ }
+
+ tiled_offset1 = tiled_offset1 + temp4 * 2048;
+ temp2 = yuv420_width - right - j;
+ if (temp2 > 192) {
+ memcpy(yuv420_dest + linear_offset, nv12t_src + tiled_offset, 64);
+ memcpy(yuv420_dest + linear_offset + 64, nv12t_src + tiled_offset + 2048, 64);
+ memcpy(yuv420_dest + linear_offset + 128, nv12t_src + tiled_offset1, 64);
+ memcpy(yuv420_dest + linear_offset + 192, nv12t_src + tiled_offset1 + 2048, temp2 - 192);
+ } else if (temp2 > 128) {
+ memcpy(yuv420_dest + linear_offset, nv12t_src + tiled_offset, 64);
+ memcpy(yuv420_dest + linear_offset + 64, nv12t_src + tiled_offset + 2048, 64);
+ memcpy(yuv420_dest + linear_offset + 128, nv12t_src + tiled_offset1, temp2 - 128);
+ } else if (temp2 > 64) {
+ memcpy(yuv420_dest + linear_offset, nv12t_src + tiled_offset, 64);
+ memcpy(yuv420_dest + linear_offset + 64, nv12t_src + tiled_offset + 2048, temp2 - 64);
+ } else {
+ memcpy(yuv420_dest + linear_offset, nv12t_src + tiled_offset, temp2);
+ }
+ }
+ } else if (temp1 >= 64) {
+ for (i = top; i < (yuv420_height - bottom); i++) {
+ j = left;
+ tiled_offset = __tile_4x2_read(yuv420_width, yuv420_height, j, i);
+ temp2 = ((j + 64) >> 6) << 6;
+ temp2 = temp2 - j;
+ linear_offset = temp1 * (i - top);
+ temp4 = j & 0x3;
+ tiled_offset = tiled_offset + temp4;
+ memcpy(yuv420_dest + linear_offset, nv12t_src + tiled_offset, temp2);
+ linear_offset = linear_offset + temp2;
+ j = j + temp2;
+ if ((j + 64) <= temp3) {
+ tiled_offset = __tile_4x2_read(yuv420_width, yuv420_height, j, i);
+ memcpy(yuv420_dest + linear_offset, nv12t_src + tiled_offset, 64);
+ linear_offset = linear_offset + 64;
+ j += 64;
+ }
+ if ((j + 64) <= temp3) {
+ tiled_offset = __tile_4x2_read(yuv420_width, yuv420_height, j, i);
+ memcpy(yuv420_dest+linear_offset, nv12t_src + tiled_offset, 64);
+ linear_offset = linear_offset + 64;
+ j += 64;
+ }
+ if (j < temp3) {
+ tiled_offset = __tile_4x2_read(yuv420_width, yuv420_height, j, i);
+ temp2 = temp3 - j;
+ memcpy(yuv420_dest + linear_offset, nv12t_src + tiled_offset, temp2);
+ }
+ }
+ } else {
+ for (i = top; i < (yuv420_height - bottom); i++) {
+ linear_offset = temp1 * (i - top);
+ for (j = left; j < (yuv420_width - right); j += 2) {
+ tiled_offset = __tile_4x2_read(yuv420_width, yuv420_height, j, i);
+ temp4 = j & 0x3;
+ tiled_offset = tiled_offset + temp4;
+ memcpy(yuv420_dest + linear_offset, nv12t_src + tiled_offset, 2);
+ linear_offset = linear_offset + 2;
+ }
+ }
+ }
+}
+
+#ifdef CAPTURE_OUTPUT_DUMP /* for capture output dump */
+static void
+capture_output_dump(mmplayer_t *player)
+{
+ unsigned char *temp = NULL;
+ char file[100] = { 0, };
+ FILE *fp = NULL;
+ int ret = 0;
+ int i = 0, j = 0;
+
+ LOGE("capture output dump start. size = %d", player->capture.size);
+ sprintf(file, "/tmp/dec_output_dump_%dx%d.yuv", player->captured.width[0], player->captured.height[0]);
+ fp = fopen(file, "ab");
+
+ for (i = 0; i < player->captured.plane_num; i++) {
+ temp = player->captured.data[i];
+
+ for (j = 0; j < player->captured.height[i]; j++) {
+ ret = fwrite(temp, player->captured.width[i], 1, fp);
+ temp += player->captured.stride_width[i];
+ }
+ }
+ LOGE("capture yuv dumped!! ret = %d", ret);
+ fclose(fp);
+
+ temp = (unsigned char *)player->capture.data;
+ sprintf(file, "/tmp/dec_output_dump_%dx%d.rgb", player->captured.width[0], player->captured.height[0]);
+ fp = fopen(file, "ab");
+ ret = fwrite(temp, player->capture.size, 1, fp);
+ fclose(fp);
+ LOGE("capture rgb dumped!! ret = %d", ret);
+}
+#endif
+
+static int
+__mm_player_convert_NV12_tiled(mmplayer_t *player)
+{
+ /* Colorspace conversion : NV12T-> NV12-> RGB888 */
+ int i;
+ int ret = MM_ERROR_NONE;
+ unsigned char *src_buffer = NULL;
+ unsigned char *linear_y_plane = NULL;
+ unsigned char *linear_uv_plane = NULL;
+ guint linear_y_plane_size;
+ guint linear_uv_plane_size;
+ guint width = player->captured.width[0];
+ guint height = player->captured.height[0];
+
+ linear_y_plane_size = width * height;
+ linear_uv_plane_size = linear_y_plane_size / 2;
+
+ if (!linear_y_plane_size || !linear_uv_plane_size) {
+ LOGE("invalid plane size");
+ return MM_ERROR_PLAYER_INTERNAL;
+ }
+ linear_y_plane = (unsigned char *)g_malloc(linear_y_plane_size);
+ linear_uv_plane = (unsigned char *)g_malloc(linear_uv_plane_size);
+
+ /* NV12 tiled to linear */
+ __csc_tiled_to_linear_crop(linear_y_plane,
+ player->captured.data[0], width, height, 0, 0, 0, 0);
+ __csc_tiled_to_linear_crop(linear_uv_plane,
+ player->captured.data[1], width, height / 2, 0, 0, 0, 0);
+
+ src_buffer = (unsigned char *)g_malloc(linear_y_plane_size + linear_uv_plane_size);
+
+ memcpy(src_buffer, linear_y_plane, linear_y_plane_size);
+ memcpy(src_buffer + linear_y_plane_size, linear_uv_plane, linear_uv_plane_size);
+
+ /* NV12 linear to RGB888 */
+ ret = __mm_player_convert_colorspace(player, src_buffer, (size_t)(linear_y_plane_size + linear_uv_plane_size),
+ MM_UTIL_COLOR_NV12, width, height, MM_UTIL_COLOR_RGB24);
+
+ MMPLAYER_FREEIF(src_buffer);
+ MMPLAYER_FREEIF(linear_y_plane);
+ MMPLAYER_FREEIF(linear_uv_plane);
+
+ for (i = 0; i < player->captured.plane_num; i++)
+ MMPLAYER_FREEIF(player->captured.data[i]);
+
+ return ret;
+}
+
+static int
+__mm_player_convert_NV12(mmplayer_t *player)
+{
+ unsigned char *src_buffer = NULL;
+ unsigned char *p_buf = NULL;
+ unsigned char *temp = NULL;
+ int planes[MAX_BUFFER_PLANE] = {0, };
+ int ret = MM_ERROR_NONE;
+ int i, j;
+
+ /* using original width otherwise, app can't know aligned to resize */
+ planes[0] = player->captured.stride_width[0] * player->captured.stride_height[0];
+ planes[1] = player->captured.stride_width[1] * player->captured.stride_height[1];
+ guint src_buffer_size = planes[0] + planes[1];
+
+ if (!src_buffer_size) {
+ LOGE("invalid data size");
+ return MM_ERROR_PLAYER_INTERNAL;
+ }
+ src_buffer = (unsigned char *)g_malloc(src_buffer_size);
+
+ p_buf = src_buffer;
+
+ temp = player->captured.data[0];
+
+ /* set Y plane */
+ for (i = 0; i < player->captured.height[0]; i++) {
+ memcpy(p_buf, temp, player->captured.width[0]);
+ p_buf += player->captured.width[0];
+ temp += player->captured.stride_width[0];
+ }
+
+ temp = player->captured.data[1];
+
+ /* set UV plane*/
+ for (j = 0; j < player->captured.height[1]; j++) {
+ memcpy(p_buf, temp, player->captured.width[1]);
+ p_buf += player->captured.width[1];
+ temp += player->captured.stride_width[1];
+ }
+
+ /* NV12 -> RGB888 */
+ ret = __mm_player_convert_colorspace(player, (unsigned char *)src_buffer, (size_t)src_buffer_size,
+ MM_UTIL_COLOR_NV12, player->captured.width[0],
+ player->captured.height[0], MM_UTIL_COLOR_RGB24);
+
+#ifdef CAPTURE_OUTPUT_DUMP
+ capture_output_dump(player);
+#endif
+ MMPLAYER_FREEIF(src_buffer);
+
+ for (i = 0; i < player->captured.plane_num; i++)
+ MMPLAYER_FREEIF(player->captured.data[i]);
+
+ return ret;
+}
+
+static int
+__mm_player_convert_I420(mmplayer_t *player)
+{
+ unsigned char *src_buffer = NULL;
+ unsigned char *p_buf = NULL;
+ unsigned char *temp = NULL;
+ int planes[MAX_BUFFER_PLANE] = {0, };
+ int ret = MM_ERROR_NONE;
+ int i;
+
+ /* using original width otherwise, app can't know aligned to resize */
+ planes[0] = player->captured.stride_width[0] * player->captured.stride_height[0];
+ planes[1] = planes[2] = (player->captured.stride_width[0] >> 1)
+ * (player->captured.stride_height[0] >> 1);
+
+ if (!planes[0] || !planes[1] || !planes[2]) {
+ LOGE("invalid plane size");
+ return MM_ERROR_PLAYER_INTERNAL;
+ }
+ src_buffer = (unsigned char *)g_malloc(planes[0] + planes[1] + planes[2]);
+
+ /* set Y plane */
+ p_buf = src_buffer;
+
+ temp = player->captured.data[0];
+
+ for (i = 0; i < player->captured.height[0]; i++) {
+ memcpy(p_buf, temp, player->captured.width[0]);
+ temp += player->captured.stride_width[0];
+ p_buf += player->captured.width[0];
+ }
+
+ /* set U plane */
+ temp = player->captured.data[1];
+
+ for (i = 0; i < player->captured.height[1]; i++) {
+ memcpy(p_buf, temp, player->captured.width[1]);
+ temp += player->captured.stride_width[1];
+ p_buf += player->captured.width[1];
+ }
+
+ /* set V plane */
+ temp = player->captured.data[2];
+
+ for (i = 0; i < player->captured.height[2]; i++) {
+ memcpy(p_buf, temp, player->captured.width[2]);
+ temp += player->captured.stride_width[2];
+ p_buf += player->captured.width[2];
+ }
+
+ /* I420 -> RGB888 */
+ ret = __mm_player_convert_colorspace(player, (unsigned char *)src_buffer, (size_t)(planes[0] + planes[1] + planes[2]),
+ MM_UTIL_COLOR_I420, player->captured.width[0], player->captured.height[0], MM_UTIL_COLOR_RGB24);
+
+#ifdef CAPTURE_OUTPUT_DUMP
+ capture_output_dump(player);
+#endif
+ MMPLAYER_FREEIF(src_buffer);
+
+ for (i = 0; i < player->captured.plane_num; i++)
+ MMPLAYER_FREEIF(player->captured.data[i]);
+
+ return ret;
+}
+
+static int
+__mm_player_convert_BGRx(mmplayer_t *player)