android_nativewindow.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /*****************************************************************************
  2. * android_nativewindow.c
  3. *****************************************************************************
  4. *
  5. * Copyright (c) 2013 Bilibili
  6. * copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
  7. *
  8. * This file is part of ijkPlayer.
  9. *
  10. * ijkPlayer is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU Lesser General Public
  12. * License as published by the Free Software Foundation; either
  13. * version 2.1 of the License, or (at your option) any later version.
  14. *
  15. * ijkPlayer is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with ijkPlayer; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. */
  24. #include "android_nativewindow.h"
  25. #include <assert.h>
  26. #include <android/native_window.h>
  27. #include "../ijksdl_vout.h"
  28. #include "../ijksdl_vout_internal.h"
  29. #include "../ffmpeg/ijksdl_inc_ffmpeg.h"
  30. #include "ijksdl_inc_internal_android.h"
  31. #ifdef SDLTRACE
  32. #undef SDLTRACE
  33. #define SDLTRACE(...)
  34. #endif
  35. static int android_render_yv12_on_yv12(ANativeWindow_Buffer *out_buffer, const SDL_VoutOverlay *overlay)
  36. {
  37. // SDLTRACE("SDL_VoutAndroid: android_render_yv12_on_yv12(%p)", overlay);
  38. assert(overlay->format == SDL_FCC_YV12);
  39. assert(overlay->planes == 3);
  40. int min_height = IJKMIN(out_buffer->height, overlay->h);
  41. int dst_y_stride = out_buffer->stride;
  42. int dst_c_stride = IJKALIGN(out_buffer->stride / 2, 16);
  43. int dst_y_size = dst_y_stride * out_buffer->height;
  44. int dst_c_size = dst_c_stride * out_buffer->height / 2;
  45. // ALOGE("stride:%d/%d, size:%d/%d", dst_y_stride, dst_c_stride, dst_y_size, dst_c_size);
  46. uint8_t *dst_pixels_array[] = {
  47. out_buffer->bits,
  48. out_buffer->bits + dst_y_size,
  49. out_buffer->bits + dst_y_size + dst_c_size,
  50. };
  51. int dst_line_height[] = { min_height, min_height / 2, min_height / 2 };
  52. int dst_line_size_array[] = { dst_y_stride, dst_c_stride, dst_c_stride };
  53. for (int i = 0; i < 3; ++i) {
  54. int dst_line_size = dst_line_size_array[i];
  55. int src_line_size = overlay->pitches[i];
  56. int line_height = dst_line_height[i];
  57. uint8_t *dst_pixels = dst_pixels_array[i];
  58. const uint8_t *src_pixels = overlay->pixels[i];
  59. if (dst_line_size == src_line_size) {
  60. int plane_size = src_line_size * line_height;
  61. // ALOGE("sdl_image_copy_plane %p %p %d", dst_pixels, src_pixels, dst_plane_size);
  62. memcpy(dst_pixels, src_pixels, plane_size);
  63. } else {
  64. // TODO: 9 padding
  65. int bytewidth = IJKMIN(dst_line_size, src_line_size);
  66. // ALOGE("av_image_copy_plane %p %d %p %d %d %d", dst_pixels, dst_line_size, src_pixels, src_line_size, bytewidth, line_height);
  67. av_image_copy_plane(dst_pixels, dst_line_size, src_pixels, src_line_size, bytewidth, line_height);
  68. }
  69. }
  70. return 0;
  71. }
  72. static int android_render_on_yv12(ANativeWindow_Buffer *out_buffer, const SDL_VoutOverlay *overlay)
  73. {
  74. assert(out_buffer);
  75. assert(overlay);
  76. switch (overlay->format) {
  77. case SDL_FCC_YV12: {
  78. return android_render_yv12_on_yv12(out_buffer, overlay);
  79. }
  80. }
  81. return -1;
  82. }
  83. static int android_render_rgb_on_rgb(ANativeWindow_Buffer *out_buffer, const SDL_VoutOverlay *overlay, int bpp)
  84. {
  85. // SDLTRACE("SDL_VoutAndroid: android_render_rgb_on_rgb(%p)", overlay);
  86. assert(overlay->format == SDL_FCC_RV16);
  87. assert(overlay->planes == 1);
  88. int min_height = IJKMIN(out_buffer->height, overlay->h);
  89. int dst_stride = out_buffer->stride;
  90. int src_line_size = overlay->pitches[0];
  91. int dst_line_size = dst_stride * bpp / 8;
  92. uint8_t *dst_pixels = out_buffer->bits;
  93. const uint8_t *src_pixels = overlay->pixels[0];
  94. if (dst_line_size == src_line_size) {
  95. int plane_size = src_line_size * min_height;
  96. // ALOGE("android_render_rgb_on_rgb (pix-match) %p %p %d", dst_pixels, src_pixels, plane_size);
  97. memcpy(dst_pixels, src_pixels, plane_size);
  98. } else {
  99. // TODO: 9 padding
  100. int bytewidth = IJKMIN(dst_line_size, src_line_size);
  101. // ALOGE("android_render_rgb_on_rgb (pix-mismatch) %p %d %p %d %d %d", dst_pixels, dst_line_size, src_pixels, src_line_size, bytewidth, min_height);
  102. av_image_copy_plane(dst_pixels, dst_line_size, src_pixels, src_line_size, bytewidth, min_height);
  103. }
  104. return 0;
  105. }
  106. static int android_render_rgb565_on_rgb565(ANativeWindow_Buffer *out_buffer, const SDL_VoutOverlay *overlay)
  107. {
  108. return android_render_rgb_on_rgb(out_buffer, overlay, 16);
  109. }
  110. static int android_render_on_rgb565(ANativeWindow_Buffer *out_buffer, const SDL_VoutOverlay *overlay)
  111. {
  112. assert(out_buffer);
  113. assert(overlay);
  114. switch (overlay->format) {
  115. case SDL_FCC_RV16: {
  116. return android_render_rgb565_on_rgb565(out_buffer, overlay);
  117. }
  118. }
  119. return -1;
  120. }
  121. static int android_render_rgb32_on_rgb8888(ANativeWindow_Buffer *out_buffer, const SDL_VoutOverlay *overlay)
  122. {
  123. return android_render_rgb_on_rgb(out_buffer, overlay, 32);
  124. }
  125. static int android_render_on_rgb8888(ANativeWindow_Buffer *out_buffer, const SDL_VoutOverlay *overlay)
  126. {
  127. assert(out_buffer);
  128. assert(overlay);
  129. switch (overlay->format) {
  130. case SDL_FCC_RV32: {
  131. return android_render_rgb32_on_rgb8888(out_buffer, overlay);
  132. }
  133. }
  134. return -1;
  135. }
  136. typedef struct AndroidHalFourccDescriptor {
  137. Uint32 fcc_or_hal;
  138. const char* name;
  139. int hal_format;
  140. int (*render)(ANativeWindow_Buffer *native_buffer, const SDL_VoutOverlay *overlay);
  141. } AndroidHalFourccDescriptor;
  142. static AndroidHalFourccDescriptor g_hal_fcc_map[] = {
  143. // YV12
  144. { HAL_PIXEL_FORMAT_YV12, "HAL_YV12", HAL_PIXEL_FORMAT_YV12, android_render_on_yv12 },
  145. { SDL_FCC_YV12, "YV12", HAL_PIXEL_FORMAT_YV12, android_render_on_yv12 },
  146. // RGB565
  147. { HAL_PIXEL_FORMAT_RGB_565, "HAL_RGB_565", HAL_PIXEL_FORMAT_RGB_565, android_render_on_rgb565 },
  148. { SDL_FCC_RV16, "RV16", HAL_PIXEL_FORMAT_RGB_565, android_render_on_rgb565 },
  149. // RGB8888
  150. { HAL_PIXEL_FORMAT_RGBX_8888, "HAL_RGBX_8888", HAL_PIXEL_FORMAT_RGBX_8888, android_render_on_rgb8888 },
  151. { HAL_PIXEL_FORMAT_RGBA_8888, "HAL_RGBA_8888", HAL_PIXEL_FORMAT_RGBA_8888, android_render_on_rgb8888 },
  152. { HAL_PIXEL_FORMAT_BGRA_8888, "HAL_BGRA_8888", HAL_PIXEL_FORMAT_BGRA_8888, android_render_on_rgb8888 },
  153. { SDL_FCC_RV32, "RV32", HAL_PIXEL_FORMAT_RGBX_8888, android_render_on_rgb8888 },
  154. };
  155. AndroidHalFourccDescriptor *native_window_get_desc(int fourcc_or_hal)
  156. {
  157. for (int i = 0; i < NELEM(g_hal_fcc_map); ++i) {
  158. AndroidHalFourccDescriptor *desc = &g_hal_fcc_map[i];
  159. if (desc->fcc_or_hal == fourcc_or_hal)
  160. return desc;
  161. }
  162. return NULL;
  163. }
  164. int SDL_Android_NativeWindow_display_l(ANativeWindow *native_window, SDL_VoutOverlay *overlay)
  165. {
  166. int retval;
  167. if (!native_window)
  168. return -1;
  169. if (!overlay) {
  170. ALOGE("SDL_Android_NativeWindow_display_l: NULL overlay");
  171. return -1;
  172. }
  173. if (overlay->w <= 0 || overlay->h <= 0) {
  174. ALOGE("SDL_Android_NativeWindow_display_l: invalid overlay dimensions(%d, %d)", overlay->w, overlay->h);
  175. return -1;
  176. }
  177. int curr_w = ANativeWindow_getWidth(native_window);
  178. int curr_h = ANativeWindow_getHeight(native_window);
  179. int curr_format = ANativeWindow_getFormat(native_window);
  180. int buff_w = IJKALIGN(overlay->w, 2);
  181. int buff_h = IJKALIGN(overlay->h, 2);
  182. AndroidHalFourccDescriptor *overlayDesc = native_window_get_desc(overlay->format);
  183. if (!overlayDesc) {
  184. ALOGE("SDL_Android_NativeWindow_display_l: unknown overlay format: %d", overlay->format);
  185. return -1;
  186. }
  187. AndroidHalFourccDescriptor *voutDesc = native_window_get_desc(curr_format);
  188. if (!voutDesc || voutDesc->hal_format != overlayDesc->hal_format) {
  189. ALOGD("ANativeWindow_setBuffersGeometry: w=%d, h=%d, f=%.4s(0x%x) => w=%d, h=%d, f=%.4s(0x%x)",
  190. curr_w, curr_h, (char*) &curr_format, curr_format,
  191. buff_w, buff_h, (char*) &overlay->format, overlay->format);
  192. retval = ANativeWindow_setBuffersGeometry(native_window, buff_w, buff_h, overlayDesc->hal_format);
  193. if (retval < 0) {
  194. ALOGE("SDL_Android_NativeWindow_display_l: ANativeWindow_setBuffersGeometry: failed %d", retval);
  195. return retval;
  196. }
  197. if (!voutDesc) {
  198. ALOGE("SDL_Android_NativeWindow_display_l: unknown hal format %d", curr_format);
  199. return -1;
  200. }
  201. }
  202. ANativeWindow_Buffer out_buffer;
  203. retval = ANativeWindow_lock(native_window, &out_buffer, NULL);
  204. if (retval < 0) {
  205. ALOGE("SDL_Android_NativeWindow_display_l: ANativeWindow_lock: failed %d", retval);
  206. return retval;
  207. }
  208. if (out_buffer.width != buff_w || out_buffer.height != buff_h) {
  209. ALOGE("unexpected native window buffer (%p)(w:%d, h:%d, fmt:'%.4s'0x%x), expecting (w:%d, h:%d, fmt:'%.4s'0x%x)",
  210. native_window,
  211. out_buffer.width, out_buffer.height, (char*)&out_buffer.format, out_buffer.format,
  212. buff_w, buff_h, (char*)&overlay->format, overlay->format);
  213. // TODO: 8 set all black
  214. ANativeWindow_unlockAndPost(native_window);
  215. ANativeWindow_setBuffersGeometry(native_window, buff_w, buff_h, overlayDesc->hal_format);
  216. return -1;
  217. }
  218. int render_ret = voutDesc->render(&out_buffer, overlay);
  219. if (render_ret < 0) {
  220. // TODO: 8 set all black
  221. // return after unlock image;
  222. }
  223. retval = ANativeWindow_unlockAndPost(native_window);
  224. if (retval < 0) {
  225. ALOGE("SDL_Android_NativeWindow_display_l: ANativeWindow_unlockAndPost: failed %d", retval);
  226. return retval;
  227. }
  228. return render_ret;
  229. }