ijksdl_vout_android_nativewindow.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. /*****************************************************************************
  2. * ijksdl_vout_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 "ijksdl_vout_android_nativewindow.h"
  25. #include <assert.h>
  26. #include <android/native_window.h>
  27. #include "ijksdl/ijksdl_vout.h"
  28. #include "ijksdl/ijksdl_vout_internal.h"
  29. #include "ijksdl/ijksdl_container.h"
  30. #include "ijksdl/ijksdl_egl.h"
  31. #include "ijksdl/ffmpeg/ijksdl_vout_overlay_ffmpeg.h"
  32. #include "ijksdl_codec_android_mediacodec.h"
  33. #include "ijksdl_inc_internal_android.h"
  34. #include "ijksdl_vout_overlay_android_mediacodec.h"
  35. #include "android_nativewindow.h"
  36. #ifndef AMCTRACE
  37. #define AMCTRACE(...)
  38. #endif
  39. struct SDL_AMediaCodecBufferProxy
  40. {
  41. int buffer_id;
  42. int buffer_index;
  43. int acodec_serial;
  44. SDL_AMediaCodecBufferInfo buffer_info;
  45. };
  46. static void SDL_AMediaCodecBufferProxy_reset(SDL_AMediaCodecBufferProxy *proxy)
  47. {
  48. memset(proxy, 0, sizeof(SDL_AMediaCodecBufferProxy));
  49. proxy->buffer_index = -1;
  50. proxy->acodec_serial = 0;
  51. }
  52. static void SDL_AMediaCodecBufferProxy_init(SDL_AMediaCodecBufferProxy *proxy)
  53. {
  54. assert(proxy);
  55. SDL_AMediaCodecBufferProxy_reset(proxy);
  56. }
  57. static void SDL_AMediaCodecBufferProxy_destroy(SDL_AMediaCodecBufferProxy *proxy)
  58. {
  59. if (!proxy)
  60. return;
  61. SDL_AMediaCodecBufferProxy_reset(proxy);
  62. }
  63. static void SDL_AMediaCodecBufferProxy_destroyP(SDL_AMediaCodecBufferProxy **proxy)
  64. {
  65. if (!proxy)
  66. return;
  67. SDL_AMediaCodecBufferProxy_destroy(*proxy);
  68. *proxy = NULL;
  69. }
  70. static void SDL_AMediaCodecBufferProxy_invalidate(SDL_AMediaCodecBufferProxy *proxy)
  71. {
  72. SDL_AMediaCodecBufferProxy_reset(proxy);
  73. }
  74. typedef struct SDL_Vout_Opaque {
  75. ANativeWindow *native_window;
  76. SDL_AMediaCodec *acodec;
  77. int null_native_window_warned; // reduce log for null window
  78. int next_buffer_id;
  79. ISDL_Array overlay_manager;
  80. ISDL_Array overlay_pool;
  81. IJK_EGL *egl;
  82. } SDL_Vout_Opaque;
  83. static SDL_VoutOverlay *func_create_overlay_l(int width, int height, int frame_format, SDL_Vout *vout)
  84. {
  85. switch (frame_format) {
  86. case IJK_AV_PIX_FMT__ANDROID_MEDIACODEC:
  87. return SDL_VoutAMediaCodec_CreateOverlay(width, height, vout);
  88. default:
  89. return SDL_VoutFFmpeg_CreateOverlay(width, height, frame_format, vout);
  90. }
  91. }
  92. static SDL_VoutOverlay *func_create_overlay(int width, int height, int frame_format, SDL_Vout *vout)
  93. {
  94. SDL_LockMutex(vout->mutex);
  95. SDL_VoutOverlay *overlay = func_create_overlay_l(width, height, frame_format, vout);
  96. SDL_UnlockMutex(vout->mutex);
  97. return overlay;
  98. }
  99. static void func_free_l(SDL_Vout *vout)
  100. {
  101. if (!vout)
  102. return;
  103. SDL_Vout_Opaque *opaque = vout->opaque;
  104. if (opaque) {
  105. SDL_AMediaCodecBufferProxy **begin = (SDL_AMediaCodecBufferProxy **)ISDL_Array__begin(&opaque->overlay_manager);
  106. SDL_AMediaCodecBufferProxy **end = (SDL_AMediaCodecBufferProxy **)ISDL_Array__end(&opaque->overlay_manager);
  107. for (; begin < end; ++begin) {
  108. SDL_AMediaCodecBufferProxy_destroyP(begin);
  109. }
  110. ISDL_Array__clear(&opaque->overlay_pool);
  111. ISDL_Array__clear(&opaque->overlay_manager);
  112. if (opaque->native_window) {
  113. ANativeWindow_release(opaque->native_window);
  114. opaque->native_window = NULL;
  115. }
  116. IJK_EGL_freep(&opaque->egl);
  117. SDL_AMediaCodec_decreaseReferenceP(&opaque->acodec);
  118. }
  119. SDL_Vout_FreeInternal(vout);
  120. }
  121. static int func_display_overlay_l(SDL_Vout *vout, SDL_VoutOverlay *overlay)
  122. {
  123. SDL_Vout_Opaque *opaque = vout->opaque;
  124. ANativeWindow *native_window = opaque->native_window;
  125. if (!native_window) {
  126. if (!opaque->null_native_window_warned) {
  127. opaque->null_native_window_warned = 1;
  128. ALOGW("func_display_overlay_l: NULL native_window");
  129. }
  130. return -1;
  131. } else {
  132. opaque->null_native_window_warned = 1;
  133. }
  134. if (!overlay) {
  135. ALOGE("func_display_overlay_l: NULL overlay");
  136. return -1;
  137. }
  138. if (overlay->w <= 0 || overlay->h <= 0) {
  139. ALOGE("func_display_overlay_l: invalid overlay dimensions(%d, %d)", overlay->w, overlay->h);
  140. return -1;
  141. }
  142. switch(overlay->format) {
  143. case SDL_FCC__AMC: {
  144. // only ANativeWindow support
  145. IJK_EGL_terminate(opaque->egl);
  146. return SDL_VoutOverlayAMediaCodec_releaseFrame_l(overlay, NULL, true);
  147. }
  148. case SDL_FCC_RV24:
  149. case SDL_FCC_I420:
  150. case SDL_FCC_I444P10LE: {
  151. // only GLES support
  152. if (opaque->egl)
  153. return IJK_EGL_display(opaque->egl, native_window, overlay);
  154. break;
  155. }
  156. case SDL_FCC_YV12:
  157. case SDL_FCC_RV16:
  158. case SDL_FCC_RV32: {
  159. // both GLES & ANativeWindow support
  160. if (vout->overlay_format == SDL_FCC__GLES2 && opaque->egl)
  161. return IJK_EGL_display(opaque->egl, native_window, overlay);
  162. break;
  163. }
  164. }
  165. // fallback to ANativeWindow
  166. IJK_EGL_terminate(opaque->egl);
  167. return SDL_Android_NativeWindow_display_l(native_window, overlay);
  168. }
  169. static int func_display_overlay(SDL_Vout *vout, SDL_VoutOverlay *overlay)
  170. {
  171. SDL_LockMutex(vout->mutex);
  172. int retval = func_display_overlay_l(vout, overlay);
  173. SDL_UnlockMutex(vout->mutex);
  174. return retval;
  175. }
  176. static SDL_Class g_nativewindow_class = {
  177. .name = "ANativeWindow_Vout",
  178. };
  179. SDL_Vout *SDL_VoutAndroid_CreateForANativeWindow()
  180. {
  181. SDL_Vout *vout = SDL_Vout_CreateInternal(sizeof(SDL_Vout_Opaque));
  182. if (!vout)
  183. return NULL;
  184. SDL_Vout_Opaque *opaque = vout->opaque;
  185. opaque->native_window = NULL;
  186. if (ISDL_Array__init(&opaque->overlay_manager, 32))
  187. goto fail;
  188. if (ISDL_Array__init(&opaque->overlay_pool, 32))
  189. goto fail;
  190. opaque->egl = IJK_EGL_create();
  191. if (!opaque->egl)
  192. goto fail;
  193. vout->opaque_class = &g_nativewindow_class;
  194. vout->create_overlay = func_create_overlay;
  195. vout->free_l = func_free_l;
  196. vout->display_overlay = func_display_overlay;
  197. return vout;
  198. fail:
  199. func_free_l(vout);
  200. return NULL;
  201. }
  202. static void SDL_VoutAndroid_invalidateAllBuffers_l(SDL_Vout *vout)
  203. {
  204. AMCTRACE("%s\n", __func__);
  205. SDL_Vout_Opaque *opaque = vout->opaque;
  206. SDL_AMediaCodecBufferProxy **begin = (SDL_AMediaCodecBufferProxy **)ISDL_Array__begin(&opaque->overlay_manager);
  207. SDL_AMediaCodecBufferProxy **end = (SDL_AMediaCodecBufferProxy **)ISDL_Array__end(&opaque->overlay_manager);
  208. for (; begin < end; ++begin) {
  209. SDL_AMediaCodecBufferProxy_invalidate(*begin);
  210. }
  211. }
  212. void SDL_VoutAndroid_invalidateAllBuffers(SDL_Vout *vout)
  213. {
  214. SDL_LockMutex(vout->mutex);
  215. SDL_VoutAndroid_invalidateAllBuffers_l(vout);
  216. SDL_UnlockMutex(vout->mutex);
  217. }
  218. static void SDL_VoutAndroid_SetNativeWindow_l(SDL_Vout *vout, ANativeWindow *native_window)
  219. {
  220. AMCTRACE("%s(%p, %p)\n", __func__, vout, native_window);
  221. SDL_Vout_Opaque *opaque = vout->opaque;
  222. if (opaque->native_window == native_window) {
  223. if (native_window == NULL) {
  224. // always invalidate buffers, if native_window is changed
  225. SDL_VoutAndroid_invalidateAllBuffers_l(vout);
  226. }
  227. return;
  228. }
  229. IJK_EGL_terminate(opaque->egl);
  230. SDL_VoutAndroid_invalidateAllBuffers_l(vout);
  231. if (opaque->native_window)
  232. ANativeWindow_release(opaque->native_window);
  233. if (native_window)
  234. ANativeWindow_acquire(native_window);
  235. opaque->native_window = native_window;
  236. opaque->null_native_window_warned = 0;
  237. }
  238. void SDL_VoutAndroid_SetNativeWindow(SDL_Vout *vout, ANativeWindow *native_window)
  239. {
  240. SDL_LockMutex(vout->mutex);
  241. SDL_VoutAndroid_SetNativeWindow_l(vout, native_window);
  242. SDL_UnlockMutex(vout->mutex);
  243. }
  244. static void SDL_VoutAndroid_setAMediaCodec_l(SDL_Vout *vout, SDL_AMediaCodec *acodec)
  245. {
  246. AMCTRACE("%s(%p)\n", __func__, acodec);
  247. SDL_Vout_Opaque *opaque = vout->opaque;
  248. if (opaque->acodec == acodec)
  249. return;
  250. SDL_VoutAndroid_invalidateAllBuffers_l(vout);
  251. SDL_AMediaCodec_decreaseReferenceP(&opaque->acodec);
  252. opaque->acodec = acodec;
  253. if (opaque->acodec)
  254. SDL_AMediaCodec_increaseReference(opaque->acodec);
  255. }
  256. void SDL_VoutAndroid_setAMediaCodec(SDL_Vout *vout, SDL_AMediaCodec *acodec)
  257. {
  258. SDL_LockMutex(vout->mutex);
  259. SDL_VoutAndroid_setAMediaCodec_l(vout, acodec);
  260. SDL_UnlockMutex(vout->mutex);
  261. }
  262. SDL_AMediaCodec *SDL_VoutAndroid_peekAMediaCodec(SDL_Vout *vout)
  263. {
  264. SDL_Vout_Opaque *opaque = vout->opaque;
  265. SDL_AMediaCodec *acodec = NULL;
  266. SDL_LockMutex(vout->mutex);
  267. acodec = opaque->acodec;
  268. SDL_UnlockMutex(vout->mutex);
  269. return acodec;
  270. }
  271. static SDL_AMediaCodecBufferProxy *SDL_VoutAndroid_obtainBufferProxy_l(SDL_Vout *vout, int acodec_serial, int buffer_index, SDL_AMediaCodecBufferInfo *buffer_info)
  272. {
  273. SDL_Vout_Opaque *opaque = vout->opaque;
  274. SDL_AMediaCodecBufferProxy *proxy = NULL;
  275. if (ISDL_Array__size(&opaque->overlay_pool) > 0) {
  276. proxy = ISDL_Array__pop_back(&opaque->overlay_pool);
  277. SDL_AMediaCodecBufferProxy_reset(proxy);
  278. } else {
  279. proxy = (SDL_AMediaCodecBufferProxy *)mallocz(sizeof(SDL_AMediaCodecBufferProxy));
  280. if (!proxy)
  281. return NULL;
  282. SDL_AMediaCodecBufferProxy_init(proxy);
  283. ISDL_Array__push_back(&opaque->overlay_manager, proxy);
  284. }
  285. proxy->buffer_id = opaque->next_buffer_id++;
  286. proxy->acodec_serial = acodec_serial;
  287. proxy->buffer_index = buffer_index;
  288. proxy->buffer_info = *buffer_info;
  289. AMCTRACE("%s: [%d] ++++++++ proxy %d: vout: %d idx: %d fake: %s",
  290. __func__,
  291. proxy->buffer_id,
  292. proxy->acodec_serial,
  293. SDL_AMediaCodec_getSerial(opaque->acodec),
  294. proxy->buffer_index,
  295. (proxy->buffer_info.flags & AMEDIACODEC__BUFFER_FLAG_FAKE_FRAME) ? "YES" : "NO");
  296. return proxy;
  297. }
  298. SDL_AMediaCodecBufferProxy *SDL_VoutAndroid_obtainBufferProxy(SDL_Vout *vout, int acodec_serial, int buffer_index, SDL_AMediaCodecBufferInfo *buffer_info)
  299. {
  300. SDL_AMediaCodecBufferProxy *proxy = NULL;
  301. SDL_LockMutex(vout->mutex);
  302. proxy = SDL_VoutAndroid_obtainBufferProxy_l(vout, acodec_serial, buffer_index, buffer_info);
  303. SDL_UnlockMutex(vout->mutex);
  304. return proxy;
  305. }
  306. static int SDL_VoutAndroid_releaseBufferProxy_l(SDL_Vout *vout, SDL_AMediaCodecBufferProxy *proxy, bool render)
  307. {
  308. SDL_Vout_Opaque *opaque = vout->opaque;
  309. if (!proxy)
  310. return 0;
  311. AMCTRACE("%s: [%d] -------- proxy %d: vout: %d idx: %d render: %s fake: %s",
  312. __func__,
  313. proxy->buffer_id,
  314. proxy->acodec_serial,
  315. SDL_AMediaCodec_getSerial(opaque->acodec),
  316. proxy->buffer_index,
  317. render ? "true" : "false",
  318. (proxy->buffer_info.flags & AMEDIACODEC__BUFFER_FLAG_FAKE_FRAME) ? "YES" : "NO");
  319. ISDL_Array__push_back(&opaque->overlay_pool, proxy);
  320. if (!SDL_AMediaCodec_isSameSerial(opaque->acodec, proxy->acodec_serial)) {
  321. ALOGW("%s: [%d] ???????? proxy %d: vout: %d idx: %d render: %s fake: %s",
  322. __func__,
  323. proxy->buffer_id,
  324. proxy->acodec_serial,
  325. SDL_AMediaCodec_getSerial(opaque->acodec),
  326. proxy->buffer_index,
  327. render ? "true" : "false",
  328. (proxy->buffer_info.flags & AMEDIACODEC__BUFFER_FLAG_FAKE_FRAME) ? "YES" : "NO");
  329. return 0;
  330. }
  331. if (proxy->buffer_index < 0) {
  332. ALOGE("%s: [%d] invalid AMediaCodec buffer index %d\n", __func__, proxy->buffer_id, proxy->buffer_index);
  333. return 0;
  334. } else if (proxy->buffer_info.flags & AMEDIACODEC__BUFFER_FLAG_FAKE_FRAME) {
  335. proxy->buffer_index = -1;
  336. return 0;
  337. }
  338. sdl_amedia_status_t amc_ret = SDL_AMediaCodec_releaseOutputBuffer(opaque->acodec, proxy->buffer_index, render);
  339. if (amc_ret != SDL_AMEDIA_OK) {
  340. ALOGW("%s: [%d] !!!!!!!! proxy %d: vout: %d idx: %d render: %s, fake: %s",
  341. __func__,
  342. proxy->buffer_id,
  343. proxy->acodec_serial,
  344. SDL_AMediaCodec_getSerial(opaque->acodec),
  345. proxy->buffer_index,
  346. render ? "true" : "false",
  347. (proxy->buffer_info.flags & AMEDIACODEC__BUFFER_FLAG_FAKE_FRAME) ? "YES" : "NO");
  348. proxy->buffer_index = -1;
  349. return -1;
  350. }
  351. proxy->buffer_index = -1;
  352. return 0;
  353. }
  354. static int SDL_VoutAndroid_releaseBufferProxy(SDL_Vout *vout, SDL_AMediaCodecBufferProxy *proxy, bool render)
  355. {
  356. int ret = 0;
  357. if (!proxy)
  358. return 0;
  359. SDL_LockMutex(vout->mutex);
  360. ret = SDL_VoutAndroid_releaseBufferProxy_l(vout, proxy, render);
  361. SDL_UnlockMutex(vout->mutex);
  362. return ret;
  363. }
  364. int SDL_VoutAndroid_releaseBufferProxyP(SDL_Vout *vout, SDL_AMediaCodecBufferProxy **proxy, bool render)
  365. {
  366. int ret = 0;
  367. if (!proxy)
  368. return 0;
  369. ret = SDL_VoutAndroid_releaseBufferProxy(vout, *proxy, render);
  370. *proxy = NULL;
  371. return ret;
  372. }
  373. int SDL_VoutAndroid_releaseBufferProxyP_l(SDL_Vout *vout, SDL_AMediaCodecBufferProxy **proxy, bool render)
  374. {
  375. int ret = 0;
  376. if (!proxy)
  377. return 0;
  378. ret = SDL_VoutAndroid_releaseBufferProxy_l(vout, *proxy, render);
  379. *proxy = NULL;
  380. return ret;
  381. }