diff --git a/android/ijkplayer/build.gradle b/android/ijkplayer/build.gradle index 93024d17ba..37688f869f 100644 --- a/android/ijkplayer/build.gradle +++ b/android/ijkplayer/build.gradle @@ -17,7 +17,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.6.1' + classpath 'com.android.tools.build:gradle:3.6.2' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7' diff --git a/android/ijkplayer/fijkplayer-full/.gitignore b/android/ijkplayer/fijkplayer-full/.gitignore index 2c2b962dab..7b5eb18ad4 100644 --- a/android/ijkplayer/fijkplayer-full/.gitignore +++ b/android/ijkplayer/fijkplayer-full/.gitignore @@ -1,2 +1,3 @@ build/ .cxx/ +.externalNativeBuild/ diff --git a/android/ijkplayer/ijkplayer-example/src/main/res/xml/settings.xml b/android/ijkplayer/ijkplayer-example/src/main/res/xml/settings.xml index 502265f0e5..908ac4a985 100644 --- a/android/ijkplayer/ijkplayer-example/src/main/res/xml/settings.xml +++ b/android/ijkplayer/ijkplayer-example/src/main/res/xml/settings.xml @@ -43,7 +43,6 @@ android:summary="@string/pref_summary_amc_oes_render" android:title="@string/pref_title_amc_oes_render"/> 0; } - private static class EventHandler extends Handler { private final WeakReference mWeakPlayer; public EventHandler(IjkMediaPlayer mp, Looper looper) { super(looper); - mWeakPlayer = new WeakReference(mp); + mWeakPlayer = new WeakReference<>(mp); } @Override diff --git a/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/MediaCodecSurface.java b/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/MediaCodecSurface.java index ebd1e19cbf..7c7477145c 100644 --- a/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/MediaCodecSurface.java +++ b/android/ijkplayer/ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/MediaCodecSurface.java @@ -77,10 +77,14 @@ public void detachFromGLContext() { public void release() { DebugLog.d("MediaCodecSurface", "release()," + mReleased); mReleased = true; - mSurfaceTexture.detachFromGLContext(); - mSurfaceTexture.release(); - mSurfaceTexture = null; - mSurface.release(); - mSurface = null; + //mSurfaceTexture.detachFromGLContext(); + if (mSurfaceTexture != null) { + mSurfaceTexture.release(); + mSurfaceTexture = null; + } + if (mSurface != null) { + mSurface.release(); + mSurface = null; + } } } diff --git a/desktop/CMakeLists.txt b/desktop/CMakeLists.txt index 510ace7e96..530c221d76 100644 --- a/desktop/CMakeLists.txt +++ b/desktop/CMakeLists.txt @@ -97,7 +97,7 @@ set(IJK_DESKTOP_UNI ON) set(FIJKPLAYER_SOURCE ${CMAKE_CURRENT_LIST_DIR}/sources/ijkplayer_desktop.h ${CMAKE_CURRENT_LIST_DIR}/sources/ijkplayer_desktop.c - #${CMAKE_CURRENT_LIST_DIR}/glad/include/glad/glad.h + # ${CMAKE_CURRENT_LIST_DIR}/glad/include/glad/glad.h ${CMAKE_CURRENT_LIST_DIR}/glfw/deps/glad_gl.c ) @@ -108,8 +108,8 @@ add_subdirectory(../ijkmedia ijkmedia) target_include_directories(IjkPlayer PRIVATE ${IJKROOT_PATH}/ijkmedia) target_include_directories(IjkPlayer PRIVATE ${IJK_FFMPAG_BUILD_DIR}/include) target_include_directories(IjkPlayer PRIVATE "${IJK_DESKTOP_PTHREAD_BUILD_DIR}/../../include") -#target_include_directories(IjkPlayer PRIVATE glad/include) target_include_directories(IjkPlayer PRIVATE glfw/deps) +target_include_directories(IjkPlayer PRIVATE glfw/include) target_link_libraries(IjkPlayer ijksdl_static ijkplayer_static yuv) @@ -198,7 +198,7 @@ add_subdirectory(glfw) #target_link_libraries(IjkPlayer glfw) add_executable(tuidemo WIN32 MACOSX_BUNDLE ${CMAKE_CURRENT_LIST_DIR}/sources/ijkplayer_demo.c) -# target_include_directories(tuidemo PRIVATE glad/include) +target_include_directories(tuidemo PRIVATE glad/include) target_include_directories(tuidemo PRIVATE glfw/include) target_include_directories(tuidemo PRIVATE glfw/deps) diff --git a/desktop/sources/ijkplayer_demo.c b/desktop/sources/ijkplayer_demo.c index 24b9473049..9adef9ecb4 100644 --- a/desktop/sources/ijkplayer_demo.c +++ b/desktop/sources/ijkplayer_demo.c @@ -184,7 +184,7 @@ int main(int argc, char *argv[]) { info.fp = fp; ijkff_set_event_cb(fp, &info, demo_event_cb); - ijkff_set_option(fp, "fcc-i420", "overlay-format", IJK_OPT_CATEGORY_PLAYER); + ijkff_set_option(fp, "fcc-bgra", "overlay-format", IJK_OPT_CATEGORY_PLAYER); ijkff_set_data_source(fp, "https://player.alicdn.com/video/aliyunmedia.mp4"); SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_AUDIO); diff --git a/ijkmedia/ijkplayer/CMakeLists.txt b/ijkmedia/ijkplayer/CMakeLists.txt index 9a4de6ba37..713cd84eb7 100644 --- a/ijkmedia/ijkplayer/CMakeLists.txt +++ b/ijkmedia/ijkplayer/CMakeLists.txt @@ -112,6 +112,10 @@ else () set(IJKPLAYER_LIB_NAME ijkplayer) endif () +if (IJK_DESKTOP_UNI) + target_include_directories(${IJKPLAYER_LIB_NAME} PRIVATE ${IJKROOT_PATH}/desktop/glfw/deps) + target_include_directories(${IJKPLAYER_LIB_NAME} PRIVATE ${IJKROOT_PATH}/desktop/glfw/include) +endif () target_include_directories(${IJKPLAYER_LIB_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}) target_include_directories(${IJKPLAYER_LIB_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/..) target_include_directories(${IJKPLAYER_LIB_NAME} PRIVATE ${IJK_FFMPAG_BUILD_DIR}/include) diff --git a/ijkmedia/ijkplayer/ff_ffplay.c b/ijkmedia/ijkplayer/ff_ffplay.c index 0adb0b612c..c95f1ab558 100755 --- a/ijkmedia/ijkplayer/ff_ffplay.c +++ b/ijkmedia/ijkplayer/ff_ffplay.c @@ -3823,15 +3823,20 @@ static int video_refresh_thread(void *arg) double remaining_time = 0.0; while (!is->abort_request) { if (remaining_time > 0.0) - av_usleep((int)(int64_t)(remaining_time * 1000000.0)); + av_usleep((uint)(uint64_t)(remaining_time * 1000000.0)); remaining_time = REFRESH_RATE; if (ffp->cover_after_prepared && !ffp->first_video_frame_rendered) { is->force_refresh = true; } + if (is->paused) { + SDL_Delay(1000/24); + is->force_refresh = true; + } if (is->show_mode != SHOW_MODE_NONE && (!is->paused || is->force_refresh)) video_refresh(ffp, &remaining_time); } - + if (ffp->vout) + SDL_VoutFreeContext(ffp->vout); return 0; } diff --git a/ijkmedia/ijkplayer/ff_ffplay_def.h b/ijkmedia/ijkplayer/ff_ffplay_def.h index a40f4c98d0..33cde10fb6 100755 --- a/ijkmedia/ijkplayer/ff_ffplay_def.h +++ b/ijkmedia/ijkplayer/ff_ffplay_def.h @@ -273,6 +273,11 @@ typedef struct Decoder { int first_frame_decoded; } Decoder; + +typedef enum ShowMode { + SHOW_MODE_NONE = -1, SHOW_MODE_VIDEO = 0, SHOW_MODE_WAVES, SHOW_MODE_RDFT, SHOW_MODE_NB +} ShowMode; + typedef struct VideoState { SDL_Thread *read_tid; AVInputFormat *iformat; @@ -336,9 +341,7 @@ typedef struct VideoState { int frame_drops_late; int continuous_frame_drops_early; - enum ShowMode { - SHOW_MODE_NONE = -1, SHOW_MODE_VIDEO = 0, SHOW_MODE_WAVES, SHOW_MODE_RDFT, SHOW_MODE_NB - } show_mode; + ShowMode show_mode; int16_t sample_array[SAMPLE_ARRAY_SIZE]; int sample_array_index; int last_i_start; diff --git a/ijkmedia/ijksdl/CMakeLists.txt b/ijkmedia/ijksdl/CMakeLists.txt index 3d0edb0d21..eb2e4397fa 100644 --- a/ijkmedia/ijksdl/CMakeLists.txt +++ b/ijkmedia/ijksdl/CMakeLists.txt @@ -145,7 +145,7 @@ if (IJK_DESKTOP_UNI) cmake_print_variables(SDL2_INCLUDE_DIRS) target_include_directories(ijksdl_static PRIVATE ${IJKROOT_PATH}/desktop/glfw/include) - # target_include_directories(ijksdl_static PRIVATE ${IJKROOT_PATH}/desktop/glad/include) + target_include_directories(ijksdl_static PRIVATE ${IJKROOT_PATH}/desktop/glad/include) target_include_directories(ijksdl_static PRIVATE ${IJKROOT_PATH}/desktop/glfw/deps) else () add_library(ijksdl SHARED ${IJK_SDL_SOURCES}) diff --git a/ijkmedia/ijksdl/android/ijksdl_vout_android_nativewindow.c b/ijkmedia/ijksdl/android/ijksdl_vout_android_nativewindow.c index ffb631846e..d6782f22bd 100644 --- a/ijkmedia/ijksdl/android/ijksdl_vout_android_nativewindow.c +++ b/ijkmedia/ijksdl/android/ijksdl_vout_android_nativewindow.c @@ -84,6 +84,7 @@ static void SDL_AMediaCodecBufferProxy_invalidate(SDL_AMediaCodecBufferProxy *pr } typedef struct SDL_Vout_Opaque { + ANativeWindow *new_window; ANativeWindow *native_window; SDL_AMediaCodec *acodec; int null_native_window_warned; // reduce log for null window @@ -113,6 +114,22 @@ static SDL_VoutOverlay *func_create_overlay(int width, int height, int frame_for return overlay; } +static void func_free_context_l(SDL_Vout *vout) +{ + if (!vout) + return; + + SDL_Vout_Opaque *opaque = vout->opaque; + if (opaque) { + IJK_EGL_freep(&opaque->egl); + + if (opaque->native_window) { + ANativeWindow_release(opaque->native_window); + opaque->native_window = NULL; + } + } +} + static void func_free_l(SDL_Vout *vout) { if (!vout) @@ -128,13 +145,6 @@ static void func_free_l(SDL_Vout *vout) ISDL_Array__clear(&opaque->overlay_pool); ISDL_Array__clear(&opaque->overlay_manager); - if (opaque->native_window) { - ANativeWindow_release(opaque->native_window); - opaque->native_window = NULL; - } - - IJK_EGL_freep(&opaque->egl); - SDL_AMediaCodec_decreaseReferenceP(&opaque->acodec); } @@ -144,6 +154,16 @@ static void func_free_l(SDL_Vout *vout) static int func_display_overlay_l(SDL_Vout *vout, SDL_VoutOverlay *overlay) { SDL_Vout_Opaque *opaque = vout->opaque; + + if (opaque->new_window != NULL) { + if (opaque->native_window) { + ANativeWindow_release(opaque->native_window); + } + opaque->native_window = opaque->new_window; + opaque->new_window = NULL; + IJK_EGL_terminate(opaque->egl); + } + ANativeWindow *native_window = opaque->native_window; if (!native_window) { @@ -244,7 +264,7 @@ SDL_Vout *SDL_VoutAndroid_CreateForANativeWindow() vout->free_l = func_free_l; vout->display_overlay = func_display_overlay; vout->get_renderer = func_get_renderer; - + vout->free_context_l = func_free_context_l; return vout; fail: func_free_l(vout); @@ -283,8 +303,19 @@ static void SDL_VoutAndroid_SetNativeWindow_l(SDL_Vout *vout, ANativeWindow *nat return; } + if (vout->vout_type & SDL_VOUT_AMC_OES_EGL) + SDL_VoutAndroid_invalidateAllBuffers_l(vout); + + if (opaque->new_window) + ANativeWindow_release(opaque->new_window); + if (native_window) + ANativeWindow_acquire(native_window); + + opaque->new_window = native_window; + opaque->null_native_window_warned = 0; + /* IJK_EGL_terminate(opaque->egl); - SDL_VoutAndroid_invalidateAllBuffers_l(vout); + if (opaque->native_window) ANativeWindow_release(opaque->native_window); @@ -294,6 +325,8 @@ static void SDL_VoutAndroid_SetNativeWindow_l(SDL_Vout *vout, ANativeWindow *nat opaque->native_window = native_window; opaque->null_native_window_warned = 0; + + */ } void SDL_VoutAndroid_SetNativeWindow(SDL_Vout *vout, ANativeWindow *native_window) @@ -319,6 +352,7 @@ void SDL_VoutAndroid_SetSurfaceTexture(SDL_Vout *vout, JNIEnv *env, jobject amc_ } if (amc_surface) opaque->egl->amc_surface = J4A_NewGlobalRef__catchAll(env, amc_surface); + opaque->egl->amc_surface_changed = 1; SDL_UnlockMutex(vout->mutex); } diff --git a/ijkmedia/ijksdl/desktop/ijksdl_vout_sdl2_video.c b/ijkmedia/ijksdl/desktop/ijksdl_vout_sdl2_video.c index b72eb618ae..26782cb88e 100644 --- a/ijkmedia/ijksdl/desktop/ijksdl_vout_sdl2_video.c +++ b/ijkmedia/ijksdl/desktop/ijksdl_vout_sdl2_video.c @@ -65,7 +65,33 @@ static int sdl2_display(SDL_Vout_Opaque *opaque, SDL_VoutOverlay *overlay) { SDL_Renderer *renderer = opaque->renderer; - assert(overlay->format == SDL_FCC_I420); + int dest_sdl2_format = SDL_PIXELFORMAT_UNKNOWN; + bool is_yuv = false; + switch (overlay->format) { + case SDL_FCC_I420: + case SDL_FCC_IYUV: + dest_sdl2_format = SDL_PIXELFORMAT_IYUV; + is_yuv = true; + break; + case SDL_FCC_RV16: + dest_sdl2_format = SDL_PIXELFORMAT_RGB565; + break; + case SDL_FCC_RV24: + dest_sdl2_format = SDL_PIXELFORMAT_RGB888; + break; + case SDL_FCC_RV32: + dest_sdl2_format = SDL_PIXELFORMAT_BGRX8888; + break; + case SDL_FCC_BGRA: + dest_sdl2_format = SDL_PIXELFORMAT_BGRA32; + break; + case SDL_FCC_RGBA: + dest_sdl2_format = SDL_PIXELFORMAT_RGBA32; + break; + default: + break; + } + assert(dest_sdl2_format != SDL_PIXELFORMAT_UNKNOWN); Uint32 format = 0; int access = 0, w = 0, h = 0, ret = 0; @@ -74,18 +100,22 @@ static int sdl2_display(SDL_Vout_Opaque *opaque, SDL_VoutOverlay *overlay) { if (ret < 0 || format != opaque->format || w != overlay->w || h != overlay->h) { if (opaque->texture) SDL_DestroyTexture(opaque->texture); - opaque->texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, overlay->w, + opaque->texture = SDL_CreateTexture(renderer, dest_sdl2_format, SDL_TEXTUREACCESS_STREAMING, overlay->w, overlay->h); - opaque->format = SDL_PIXELFORMAT_IYUV; + opaque->format = dest_sdl2_format; } if (opaque->texture == NULL) { return -1; } SDL_Texture *texture = opaque->texture; - SDL_UpdateYUVTexture(texture, NULL, - overlay->pixels[0], overlay->pitches[0], - overlay->pixels[1], overlay->pitches[1], - overlay->pixels[2], overlay->pitches[2]); + if (is_yuv) { + SDL_UpdateYUVTexture(texture, NULL, + overlay->pixels[0], overlay->pitches[0], + overlay->pixels[1], overlay->pitches[1], + overlay->pixels[2], overlay->pitches[2]); + } else { + SDL_UpdateTexture(texture, NULL, overlay->pixels[0], overlay->pitches[0]); + } SDL_RenderCopy(renderer, texture, NULL, NULL); SDL_RenderPresent(renderer); return 0; diff --git a/ijkmedia/ijksdl/ffmpeg/ijksdl_vout_overlay_ffmpeg.c b/ijkmedia/ijksdl/ffmpeg/ijksdl_vout_overlay_ffmpeg.c index af41e4232a..e235728677 100644 --- a/ijkmedia/ijksdl/ffmpeg/ijksdl_vout_overlay_ffmpeg.c +++ b/ijkmedia/ijksdl/ffmpeg/ijksdl_vout_overlay_ffmpeg.c @@ -193,7 +193,7 @@ static int func_fill_frame(SDL_VoutOverlay *overlay, const AVFrame *frame) } break; case SDL_FCC_RV32: - dst_format = AV_PIX_FMT_0BGR32; + dst_format = AV_PIX_FMT_0RGB; break; case SDL_FCC_RV24: dst_format = AV_PIX_FMT_RGB24; @@ -202,10 +202,10 @@ static int func_fill_frame(SDL_VoutOverlay *overlay, const AVFrame *frame) dst_format = AV_PIX_FMT_RGB565; break; case SDL_FCC_BGRA: - dst_format = AV_PIX_FMT_BGR32_1; + dst_format = AV_PIX_FMT_BGRA; break; case SDL_FCC_RGBA: - dst_format = AV_PIX_FMT_RGB32_1; + dst_format = AV_PIX_FMT_RGBA; break; default: ALOGE("SDL_VoutFFmpeg_ConvertPicture: unexpected overlay format %s(%d)", @@ -393,7 +393,7 @@ SDL_VoutOverlay *SDL_VoutFFmpeg_CreateOverlay(int width, int height, int frame_f break; } case SDL_FCC_RV32: { - ff_format = AV_PIX_FMT_0BGR32; + ff_format = AV_PIX_FMT_0RGB; buf_width = IJKALIGN(width, 4); // 4 bytes per pixel opaque->planes = 1; break; diff --git a/ijkmedia/ijksdl/gles2/internal.h b/ijkmedia/ijksdl/gles2/internal.h index 97356f3207..097ca2ddf3 100644 --- a/ijkmedia/ijksdl/gles2/internal.h +++ b/ijkmedia/ijksdl/gles2/internal.h @@ -101,7 +101,7 @@ typedef struct IJK_GLES_Matrix } IJK_GLES_Matrix; void IJK_GLES2_loadOrtho(IJK_GLES_Matrix *matrix, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far); -void IJK_GLES2_Renderer_TexCoords_updateFlip(IJK_GLES2_Renderer *renderer); +void IJK_GLES2_Renderer_setFlip(IJK_GLES2_Renderer *renderer, IJK_SDL_GLES2_flip flip); const char *IJK_GLES2_getVertexShader_default(); const char *IJK_GLES2_getVertexShader_amc(); diff --git a/ijkmedia/ijksdl/gles2/renderer.c b/ijkmedia/ijksdl/gles2/renderer.c index 17a34b7c10..57d8004634 100644 --- a/ijkmedia/ijksdl/gles2/renderer.c +++ b/ijkmedia/ijksdl/gles2/renderer.c @@ -415,6 +415,14 @@ void IJK_GLES2_Renderer_TexCoords_updateFlip(IJK_GLES2_Renderer *renderer) } +void IJK_GLES2_Renderer_setFlip(IJK_GLES2_Renderer *renderer, IJK_SDL_GLES2_flip flip) +{ + if(!renderer) + return; + renderer->flip = flip; + renderer->vertices_changed = 1; +} + /* * Per-Renderer routine */ diff --git a/ijkmedia/ijksdl/gles2/renderer_amc.c b/ijkmedia/ijksdl/gles2/renderer_amc.c index ad26610824..9c0e05d76c 100644 --- a/ijkmedia/ijksdl/gles2/renderer_amc.c +++ b/ijkmedia/ijksdl/gles2/renderer_amc.c @@ -55,9 +55,9 @@ static GLboolean amc_use(IJK_GLES2_Renderer *renderer) return 0; } - ALOGI("SurfaceTexture: detachFromGLContext"); - J4AC_MediaCodecSurface__detachFromGLContext(env, opaque->amc_surface); - ALOGI("SurfaceTexture: detachFromGLContext=void"); + // ALOGI("SurfaceTexture: detachFromGLContext"); + // J4AC_MediaCodecSurface__detachFromGLContext(env, opaque->amc_surface); + // ALOGI("SurfaceTexture: detachFromGLContext=void"); if (opaque->mtx == NULL) { jfloatArray mtx = (*env)->NewFloatArray(env, 16); @@ -187,6 +187,8 @@ static void amc_flip(int flip, GLfloat *texcoords) void IJK_GLES2_Renderer_AMC_set_texture(IJK_GLES2_Renderer *renderer, jobject amc_surface) { + if (!renderer) + return; IJK_GLES2_Renderer_Opaque* opaque = renderer->opaque; if (opaque->class == &g_class) { opaque->amc_surface = amc_surface; @@ -201,6 +203,8 @@ static void amc_destroy(IJK_GLES2_Renderer *renderer) ALOGE("SDL_Android_GetApiLevel: SetupThreadEnv failed"); return; } + //if (opaque->amc_surface) + // J4AC_MediaCodecSurface__detachFromGLContext(env, opaque->amc_surface); J4A_DeleteGlobalRef(env, opaque->mtx); // J4AC_MediaCodecSurface__release(env, opaque->amc_surface); diff --git a/ijkmedia/ijksdl/ijksdl_egl.c b/ijkmedia/ijksdl/ijksdl_egl.c index 89b613344f..5f8d8e1563 100644 --- a/ijkmedia/ijksdl/ijksdl_egl.c +++ b/ijkmedia/ijksdl/ijksdl_egl.c @@ -277,6 +277,10 @@ static EGLBoolean IJK_EGL_prepareRenderer(IJK_EGL* egl, SDL_VoutOverlay *overlay IJK_EGL_Opaque *opaque = egl->opaque; + if (egl->amc_surface_changed) { + IJK_GLES2_Renderer_AMC_set_texture(opaque->renderer, egl->amc_surface); + egl->amc_surface_changed = 0; + } if (!IJK_GLES2_Renderer_isValid(opaque->renderer) || !IJK_GLES2_Renderer_isFormat(opaque->renderer, overlay->format)) { diff --git a/ijkmedia/ijksdl/ijksdl_egl.h b/ijkmedia/ijksdl/ijksdl_egl.h index 078db3d3f9..5dcecf57da 100644 --- a/ijkmedia/ijksdl/ijksdl_egl.h +++ b/ijkmedia/ijksdl/ijksdl_egl.h @@ -61,6 +61,7 @@ typedef struct IJK_EGL #if ANDROID jobject amc_surface; + int amc_surface_changed; #endif #if 0 uint8_t gles2_extensions[IJK_GLES2__MAX_EXT]; diff --git a/ijkmedia/ijksdl/ijksdl_log.c b/ijkmedia/ijksdl/ijksdl_log.c index 9bf10bd7b6..d2352ca9a4 100644 --- a/ijkmedia/ijksdl/ijksdl_log.c +++ b/ijkmedia/ijksdl/ijksdl_log.c @@ -23,6 +23,7 @@ #include "ijksdl_log.h" +#include #if ANDROID #include #endif diff --git a/ijkmedia/ijksdl/ijksdl_vout.c b/ijkmedia/ijksdl/ijksdl_vout.c index dcbdef464f..e367fe1bc0 100644 --- a/ijkmedia/ijksdl/ijksdl_vout.c +++ b/ijkmedia/ijksdl/ijksdl_vout.c @@ -52,6 +52,17 @@ void SDL_VoutFreeP(SDL_Vout **pvout) *pvout = NULL; } +void SDL_VoutFreeContext(SDL_Vout *vout) +{ + if (!vout) + return; + if (vout->free_context_l) { + SDL_LockMutex(vout->mutex); + vout->free_context_l(vout); + SDL_UnlockMutex(vout->mutex); + } +} + int SDL_VoutDisplayYUVOverlay(SDL_Vout *vout, SDL_VoutOverlay *overlay) { if (vout && overlay && vout->display_overlay) diff --git a/ijkmedia/ijksdl/ijksdl_vout.h b/ijkmedia/ijksdl/ijksdl_vout.h index aea1ca880b..bc6b2e5997 100644 --- a/ijkmedia/ijksdl/ijksdl_vout.h +++ b/ijkmedia/ijksdl/ijksdl_vout.h @@ -71,6 +71,7 @@ struct SDL_Vout { SDL_Vout_Opaque *opaque; SDL_VoutOverlay *(*create_overlay)(int width, int height, int frame_format, SDL_Vout *vout); void (*free_l)(SDL_Vout *vout); + void (*free_context_l)(SDL_Vout *vout); int (*display_overlay)(SDL_Vout *vout, SDL_VoutOverlay *overlay); int (*set_window)(SDL_Vout *vout, void *window); @@ -80,6 +81,7 @@ struct SDL_Vout { void SDL_VoutFree(SDL_Vout *vout); void SDL_VoutFreeP(SDL_Vout **pvout); +void SDL_VoutFreeContext(SDL_Vout *vout); int SDL_VoutDisplayYUVOverlay(SDL_Vout *vout, SDL_VoutOverlay *overlay); int SDL_VoutSetOverlayFormat(SDL_Vout *vout, Uint32 overlay_format, int vout_type); diff --git a/ios/IJKMediaPlayer/IJKMediaPlayer.xcodeproj/project.pbxproj b/ios/IJKMediaPlayer/IJKMediaPlayer.xcodeproj/project.pbxproj index de7102518c..ad2c3a6365 100644 --- a/ios/IJKMediaPlayer/IJKMediaPlayer.xcodeproj/project.pbxproj +++ b/ios/IJKMediaPlayer/IJKMediaPlayer.xcodeproj/project.pbxproj @@ -151,6 +151,9 @@ 21E6F4FC22C39D0500611D3D /* IJKSDLHudViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = E68B7ACD1C1E97B0001DE241 /* IJKSDLHudViewCell.h */; }; 21E6F4FD22C39D0500611D3D /* IJKVideoToolBox.h in Headers */ = {isa = PBXBuildFile; fileRef = 5407EC271DF7F93B00457BFE /* IJKVideoToolBox.h */; }; 21E6F4FE22C39D0500611D3D /* NSString+IJKMedia.h in Headers */ = {isa = PBXBuildFile; fileRef = E69808991C7EB13A0048A46C /* NSString+IJKMedia.h */; }; + 2BA9D364245DABBC0008FE27 /* ijksdl_log.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BA9D363245DABBC0008FE27 /* ijksdl_log.c */; }; + 2BA9D365245DABE80008FE27 /* ijksdl_log.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BA9D363245DABBC0008FE27 /* ijksdl_log.c */; }; + 2BA9D366245DBB540008FE27 /* ijksdl_log.c in Sources */ = {isa = PBXBuildFile; fileRef = 2BA9D363245DABBC0008FE27 /* ijksdl_log.c */; }; 4D32BC811F906E3A00CE9F03 /* IJKSDLGLViewProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D32BC801F906E3600CE9F03 /* IJKSDLGLViewProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4D32BC821F906E3B00CE9F03 /* IJKSDLGLViewProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D32BC801F906E3600CE9F03 /* IJKSDLGLViewProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4DA7F6891F2B1E270032A499 /* ijkiourlhook.c in Sources */ = {isa = PBXBuildFile; fileRef = 4DA7F6881F2B1E270032A499 /* ijkiourlhook.c */; }; @@ -424,6 +427,7 @@ 21B62DA02334C3FA005E1C40 /* IJKSDLFboGLView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IJKSDLFboGLView.m; sourceTree = ""; }; 21DAA15C2298FED6007B0784 /* libbz2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libbz2.tbd; path = usr/lib/libbz2.tbd; sourceTree = SDKROOT; }; 21E6F50322C39D0500611D3D /* IJKPlayer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = IJKPlayer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 2BA9D363245DABBC0008FE27 /* ijksdl_log.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ijksdl_log.c; sourceTree = ""; }; 454316201A66493700676070 /* ffpipeline_ios.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ffpipeline_ios.c; path = ijkmedia/ijkplayer/ios/pipeline/ffpipeline_ios.c; sourceTree = ""; }; 454316211A66493700676070 /* ffpipeline_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ffpipeline_ios.h; path = ijkmedia/ijkplayer/ios/pipeline/ffpipeline_ios.h; sourceTree = ""; }; 454316221A66493700676070 /* ffpipenode_ios_videotoolbox_vdec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ffpipenode_ios_videotoolbox_vdec.h; path = ijkmedia/ijkplayer/ios/pipeline/ffpipenode_ios_videotoolbox_vdec.h; sourceTree = ""; }; @@ -965,6 +969,7 @@ E6C459831C7030AA004831EC /* ijksdl_gles2.h */, E690400717EAFC6100CFD954 /* ijksdl_inc_internal.h */, E6CA1EE91B4FB04500BCAF89 /* ijksdl_log.h */, + 2BA9D363245DABBC0008FE27 /* ijksdl_log.c */, E6CA1EE81B4FAFCF00BCAF89 /* ijksdl_misc.h */, E690400817EAFC6100CFD954 /* ijksdl_mutex.c */, E690400917EAFC6100CFD954 /* ijksdl_mutex.h */, @@ -1475,6 +1480,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 2BA9D365245DABE80008FE27 /* ijksdl_log.c in Sources */, 21E6F47C22C39D0500611D3D /* IJKKVOController.m in Sources */, 21E6F47D22C39D0500611D3D /* ijksdl_vout.c in Sources */, 21E6F47E22C39D0500611D3D /* yuv444p10le.fsh.c in Sources */, @@ -1568,6 +1574,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 2BA9D366245DBB540008FE27 /* ijksdl_log.c in Sources */, 5450AFC41E63EA4300568494 /* IJKKVOController.m in Sources */, 5450AFC51E63EA4300568494 /* ijksdl_vout.c in Sources */, 5450AFC61E63EA4300568494 /* yuv444p10le.fsh.c in Sources */, @@ -1734,6 +1741,7 @@ E654EAAB1B6B284C00B0F2D0 /* IJKFFMoviePlayerController.m in Sources */, E69808A11C7EB2040048A46C /* IJKNotificationManager.m in Sources */, E654EAA41B6B283700B0F2D0 /* IJKMediaModule.m in Sources */, + 2BA9D364245DABBC0008FE27 /* ijksdl_log.c in Sources */, E654EAAF1B6B285900B0F2D0 /* ff_cmdutils.c in Sources */, E654EAB81B6B286400B0F2D0 /* IJKVideoToolBoxAsync.m in Sources */, E6C459991C7030B6004831EC /* renderer_yuv444p10le.c in Sources */, diff --git a/ios/IJKMediaPlayer/IJKMediaPlayer/IJKFFMediaPlayer.h b/ios/IJKMediaPlayer/IJKMediaPlayer/IJKFFMediaPlayer.h index 1bac037b46..5f4a9ec218 100644 --- a/ios/IJKMediaPlayer/IJKMediaPlayer/IJKFFMediaPlayer.h +++ b/ios/IJKMediaPlayer/IJKMediaPlayer/IJKFFMediaPlayer.h @@ -43,6 +43,12 @@ typedef NS_ENUM(NSInteger, IJKMPEventType) { IJKMPET_PLAYBACK_STATE_CHANGED = 700, }; +typedef NS_ENUM(NSInteger, IJKMPErrorCode){ + IJKMPEC_SNAPSHOT = -480, +}; + + +typedef void(^OnSnapshotBlock) (UIImage* __nullable image , NSError* __nullable error ); @class IJKFFMediaPlayer; @@ -66,6 +72,7 @@ typedef NS_ENUM(NSInteger, IJKMPEventType) { - (BOOL) isPlaying; - (void) shutdown; +- (void) takeSnapshot:(OnSnapshotBlock) block; - (long) getCurrentPosition; - (long) getDuration; - (int) seekTo:(long) msec; diff --git a/ios/IJKMediaPlayer/IJKMediaPlayer/IJKFFMediaPlayer.m b/ios/IJKMediaPlayer/IJKMediaPlayer/IJKFFMediaPlayer.m index 56cbf64a88..b0383094a8 100644 --- a/ios/IJKMediaPlayer/IJKMediaPlayer/IJKFFMediaPlayer.m +++ b/ios/IJKMediaPlayer/IJKMediaPlayer/IJKFFMediaPlayer.m @@ -47,6 +47,8 @@ @implementation IJKFFMediaPlayer { NSMutableSet> *_eventHandlers; CFDictionaryRef _optionsDictionary; + + OnSnapshotBlock _onSnapshot; #if IJK_IOS IJKSDLFboGLView* _fboView; #endif @@ -334,10 +336,31 @@ - (void) setupCVPixelBufferView:(id) cvPBView } } + +- (void) onSnapshot:(CVPixelBufferRef) pixelbuffer +{ + if (_onSnapshot != nil) { + CIImage *ciImage = [CIImage imageWithCVPixelBuffer:pixelbuffer]; + + CIContext *context = [CIContext contextWithOptions:nil]; + CGImageRef imageRef = [context createCGImage:ciImage + fromRect:CGRectMake(0, 0, + CVPixelBufferGetWidth(pixelbuffer), + CVPixelBufferGetHeight(pixelbuffer))]; + + UIImage *uiImage = [UIImage imageWithCGImage:imageRef]; + CGImageRelease(imageRef); + + _onSnapshot(uiImage, nil); + _onSnapshot = nil; + } +} + // IJKSDL GLview call this when display frame - (void) display_pixels:(IJKOverlay *)overlay { if (overlay->pixel_buffer != nil && _cvPBView != nil) { + [self onSnapshot: overlay->pixel_buffer]; [_cvPBView display_pixelbuffer:overlay->pixel_buffer]; } else if (_cvPBView != nil && overlay->format == SDL_FCC_BGRA){ CVPixelBufferRef pixelBuffer; @@ -366,6 +389,7 @@ - (void) display_pixels:(IJKOverlay *)overlay uint8_t *dst = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0); memcpy(dst, overlay->pixels[0], overlay->pitches[0] * overlay->h); CVPixelBufferUnlockBaseAddress(pixelBuffer, 0); + [self onSnapshot: pixelBuffer]; [_cvPBView display_pixelbuffer:pixelBuffer]; CVPixelBufferRelease(pixelBuffer); } @@ -378,6 +402,14 @@ - (void)display_pixelbuffer:(CVPixelBufferRef)pixelbuffer { if (_cvPBView) { [_cvPBView display_pixelbuffer:pixelbuffer]; } + [self onSnapshot: pixelbuffer]; } + +- (void) takeSnapshot:(OnSnapshotBlock) block +{ + _onSnapshot = block; +} + + @end diff --git a/ios/IJKMediaPlayer/IJKMediaPlayer/ijkmedia/ijksdl/ios/IJKSDLFboGLView.m b/ios/IJKMediaPlayer/IJKMediaPlayer/ijkmedia/ijksdl/ios/IJKSDLFboGLView.m index 212a901768..6dc07253c6 100644 --- a/ios/IJKMediaPlayer/IJKMediaPlayer/ijkmedia/ijksdl/ios/IJKSDLFboGLView.m +++ b/ios/IJKMediaPlayer/IJKMediaPlayer/ijkmedia/ijksdl/ios/IJKSDLFboGLView.m @@ -321,6 +321,7 @@ - (BOOL)setupRenderer: (SDL_VoutOverlay *) overlay return NO; IJK_GLES2_Renderer_setGravity(_renderer, _rendererGravity, _renderSize.width, _renderSize.height); + IJK_GLES2_Renderer_setFlip(_renderer, IJK_SDL_GLES2_flip_vertical); } return YES;