123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- /*****************************************************************************
- * android_nativewindow.c
- *****************************************************************************
- *
- * Copyright (c) 2013 Bilibili
- * copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
- *
- * This file is part of ijkPlayer.
- *
- * ijkPlayer is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * ijkPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with ijkPlayer; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
- #include "android_nativewindow.h"
- #include <assert.h>
- #include <android/native_window.h>
- #include "../ijksdl_vout.h"
- #include "../ijksdl_vout_internal.h"
- #include "../ffmpeg/ijksdl_inc_ffmpeg.h"
- #include "ijksdl_inc_internal_android.h"
- #ifdef SDLTRACE
- #undef SDLTRACE
- #define SDLTRACE(...)
- #endif
- static int android_render_yv12_on_yv12(ANativeWindow_Buffer *out_buffer, const SDL_VoutOverlay *overlay)
- {
- // SDLTRACE("SDL_VoutAndroid: android_render_yv12_on_yv12(%p)", overlay);
- assert(overlay->format == SDL_FCC_YV12);
- assert(overlay->planes == 3);
- int min_height = IJKMIN(out_buffer->height, overlay->h);
- int dst_y_stride = out_buffer->stride;
- int dst_c_stride = IJKALIGN(out_buffer->stride / 2, 16);
- int dst_y_size = dst_y_stride * out_buffer->height;
- int dst_c_size = dst_c_stride * out_buffer->height / 2;
- // ALOGE("stride:%d/%d, size:%d/%d", dst_y_stride, dst_c_stride, dst_y_size, dst_c_size);
- uint8_t *dst_pixels_array[] = {
- out_buffer->bits,
- out_buffer->bits + dst_y_size,
- out_buffer->bits + dst_y_size + dst_c_size,
- };
- int dst_line_height[] = { min_height, min_height / 2, min_height / 2 };
- int dst_line_size_array[] = { dst_y_stride, dst_c_stride, dst_c_stride };
- for (int i = 0; i < 3; ++i) {
- int dst_line_size = dst_line_size_array[i];
- int src_line_size = overlay->pitches[i];
- int line_height = dst_line_height[i];
- uint8_t *dst_pixels = dst_pixels_array[i];
- const uint8_t *src_pixels = overlay->pixels[i];
- if (dst_line_size == src_line_size) {
- int plane_size = src_line_size * line_height;
- // ALOGE("sdl_image_copy_plane %p %p %d", dst_pixels, src_pixels, dst_plane_size);
- memcpy(dst_pixels, src_pixels, plane_size);
- } else {
- // TODO: 9 padding
- int bytewidth = IJKMIN(dst_line_size, src_line_size);
- // ALOGE("av_image_copy_plane %p %d %p %d %d %d", dst_pixels, dst_line_size, src_pixels, src_line_size, bytewidth, line_height);
- av_image_copy_plane(dst_pixels, dst_line_size, src_pixels, src_line_size, bytewidth, line_height);
- }
- }
- return 0;
- }
- static int android_render_on_yv12(ANativeWindow_Buffer *out_buffer, const SDL_VoutOverlay *overlay)
- {
- assert(out_buffer);
- assert(overlay);
- switch (overlay->format) {
- case SDL_FCC_YV12: {
- return android_render_yv12_on_yv12(out_buffer, overlay);
- }
- }
- return -1;
- }
- static int android_render_rgb_on_rgb(ANativeWindow_Buffer *out_buffer, const SDL_VoutOverlay *overlay, int bpp)
- {
- // SDLTRACE("SDL_VoutAndroid: android_render_rgb_on_rgb(%p)", overlay);
- assert(overlay->format == SDL_FCC_RV16);
- assert(overlay->planes == 1);
- int min_height = IJKMIN(out_buffer->height, overlay->h);
- int dst_stride = out_buffer->stride;
- int src_line_size = overlay->pitches[0];
- int dst_line_size = dst_stride * bpp / 8;
- uint8_t *dst_pixels = out_buffer->bits;
- const uint8_t *src_pixels = overlay->pixels[0];
- if (dst_line_size == src_line_size) {
- int plane_size = src_line_size * min_height;
- // ALOGE("android_render_rgb_on_rgb (pix-match) %p %p %d", dst_pixels, src_pixels, plane_size);
- memcpy(dst_pixels, src_pixels, plane_size);
- } else {
- // TODO: 9 padding
- int bytewidth = IJKMIN(dst_line_size, src_line_size);
- // 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);
- av_image_copy_plane(dst_pixels, dst_line_size, src_pixels, src_line_size, bytewidth, min_height);
- }
- return 0;
- }
- static int android_render_rgb565_on_rgb565(ANativeWindow_Buffer *out_buffer, const SDL_VoutOverlay *overlay)
- {
- return android_render_rgb_on_rgb(out_buffer, overlay, 16);
- }
- static int android_render_on_rgb565(ANativeWindow_Buffer *out_buffer, const SDL_VoutOverlay *overlay)
- {
- assert(out_buffer);
- assert(overlay);
- switch (overlay->format) {
- case SDL_FCC_RV16: {
- return android_render_rgb565_on_rgb565(out_buffer, overlay);
- }
- }
- return -1;
- }
- static int android_render_rgb32_on_rgb8888(ANativeWindow_Buffer *out_buffer, const SDL_VoutOverlay *overlay)
- {
- return android_render_rgb_on_rgb(out_buffer, overlay, 32);
- }
- static int android_render_on_rgb8888(ANativeWindow_Buffer *out_buffer, const SDL_VoutOverlay *overlay)
- {
- assert(out_buffer);
- assert(overlay);
- switch (overlay->format) {
- case SDL_FCC_RV32: {
- return android_render_rgb32_on_rgb8888(out_buffer, overlay);
- }
- }
- return -1;
- }
- typedef struct AndroidHalFourccDescriptor {
- Uint32 fcc_or_hal;
- const char* name;
- int hal_format;
- int (*render)(ANativeWindow_Buffer *native_buffer, const SDL_VoutOverlay *overlay);
- } AndroidHalFourccDescriptor;
- static AndroidHalFourccDescriptor g_hal_fcc_map[] = {
- // YV12
- { HAL_PIXEL_FORMAT_YV12, "HAL_YV12", HAL_PIXEL_FORMAT_YV12, android_render_on_yv12 },
- { SDL_FCC_YV12, "YV12", HAL_PIXEL_FORMAT_YV12, android_render_on_yv12 },
- // RGB565
- { HAL_PIXEL_FORMAT_RGB_565, "HAL_RGB_565", HAL_PIXEL_FORMAT_RGB_565, android_render_on_rgb565 },
- { SDL_FCC_RV16, "RV16", HAL_PIXEL_FORMAT_RGB_565, android_render_on_rgb565 },
- // RGB8888
- { HAL_PIXEL_FORMAT_RGBX_8888, "HAL_RGBX_8888", HAL_PIXEL_FORMAT_RGBX_8888, android_render_on_rgb8888 },
- { HAL_PIXEL_FORMAT_RGBA_8888, "HAL_RGBA_8888", HAL_PIXEL_FORMAT_RGBA_8888, android_render_on_rgb8888 },
- { HAL_PIXEL_FORMAT_BGRA_8888, "HAL_BGRA_8888", HAL_PIXEL_FORMAT_BGRA_8888, android_render_on_rgb8888 },
- { SDL_FCC_RV32, "RV32", HAL_PIXEL_FORMAT_RGBX_8888, android_render_on_rgb8888 },
- };
- AndroidHalFourccDescriptor *native_window_get_desc(int fourcc_or_hal)
- {
- for (int i = 0; i < NELEM(g_hal_fcc_map); ++i) {
- AndroidHalFourccDescriptor *desc = &g_hal_fcc_map[i];
- if (desc->fcc_or_hal == fourcc_or_hal)
- return desc;
- }
- return NULL;
- }
- int SDL_Android_NativeWindow_display_l(ANativeWindow *native_window, SDL_VoutOverlay *overlay)
- {
- int retval;
- if (!native_window)
- return -1;
- if (!overlay) {
- ALOGE("SDL_Android_NativeWindow_display_l: NULL overlay");
- return -1;
- }
- if (overlay->w <= 0 || overlay->h <= 0) {
- ALOGE("SDL_Android_NativeWindow_display_l: invalid overlay dimensions(%d, %d)", overlay->w, overlay->h);
- return -1;
- }
- int curr_w = ANativeWindow_getWidth(native_window);
- int curr_h = ANativeWindow_getHeight(native_window);
- int curr_format = ANativeWindow_getFormat(native_window);
- int buff_w = IJKALIGN(overlay->w, 2);
- int buff_h = IJKALIGN(overlay->h, 2);
- AndroidHalFourccDescriptor *overlayDesc = native_window_get_desc(overlay->format);
- if (!overlayDesc) {
- ALOGE("SDL_Android_NativeWindow_display_l: unknown overlay format: %d", overlay->format);
- return -1;
- }
- AndroidHalFourccDescriptor *voutDesc = native_window_get_desc(curr_format);
- if (!voutDesc || voutDesc->hal_format != overlayDesc->hal_format) {
- ALOGD("ANativeWindow_setBuffersGeometry: w=%d, h=%d, f=%.4s(0x%x) => w=%d, h=%d, f=%.4s(0x%x)",
- curr_w, curr_h, (char*) &curr_format, curr_format,
- buff_w, buff_h, (char*) &overlay->format, overlay->format);
- retval = ANativeWindow_setBuffersGeometry(native_window, buff_w, buff_h, overlayDesc->hal_format);
- if (retval < 0) {
- ALOGE("SDL_Android_NativeWindow_display_l: ANativeWindow_setBuffersGeometry: failed %d", retval);
- return retval;
- }
- if (!voutDesc) {
- ALOGE("SDL_Android_NativeWindow_display_l: unknown hal format %d", curr_format);
- return -1;
- }
- }
- ANativeWindow_Buffer out_buffer;
- retval = ANativeWindow_lock(native_window, &out_buffer, NULL);
- if (retval < 0) {
- ALOGE("SDL_Android_NativeWindow_display_l: ANativeWindow_lock: failed %d", retval);
- return retval;
- }
- if (out_buffer.width != buff_w || out_buffer.height != buff_h) {
- ALOGE("unexpected native window buffer (%p)(w:%d, h:%d, fmt:'%.4s'0x%x), expecting (w:%d, h:%d, fmt:'%.4s'0x%x)",
- native_window,
- out_buffer.width, out_buffer.height, (char*)&out_buffer.format, out_buffer.format,
- buff_w, buff_h, (char*)&overlay->format, overlay->format);
- // TODO: 8 set all black
- ANativeWindow_unlockAndPost(native_window);
- ANativeWindow_setBuffersGeometry(native_window, buff_w, buff_h, overlayDesc->hal_format);
- return -1;
- }
- int render_ret = voutDesc->render(&out_buffer, overlay);
- if (render_ret < 0) {
- // TODO: 8 set all black
- // return after unlock image;
- }
- retval = ANativeWindow_unlockAndPost(native_window);
- if (retval < 0) {
- ALOGE("SDL_Android_NativeWindow_display_l: ANativeWindow_unlockAndPost: failed %d", retval);
- return retval;
- }
- return render_ret;
- }
|