├── MLVB-API-Example ├── .gitignore ├── Advanced │ ├── CustomVideoCapture │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── tencent │ │ │ │ └── mlvb │ │ │ │ └── customvideocapture │ │ │ │ ├── CustomVideoCaptureActivity.java │ │ │ │ └── helper │ │ │ │ ├── CustomCameraCapture.java │ │ │ │ ├── CustomFrameRender.java │ │ │ │ ├── basic │ │ │ │ ├── Frame.java │ │ │ │ ├── FrameBuffer.java │ │ │ │ ├── Size.java │ │ │ │ └── TextureFrame.java │ │ │ │ └── render │ │ │ │ ├── EGL10Helper.java │ │ │ │ ├── EGL14Helper.java │ │ │ │ ├── EGLHelper.java │ │ │ │ ├── EglCore.java │ │ │ │ └── opengl │ │ │ │ ├── GPUImageFilter.java │ │ │ │ ├── GPUImageFilterGroup.java │ │ │ │ ├── GpuImageI420Filter.java │ │ │ │ ├── OesInputFilter.java │ │ │ │ ├── OpenGlUtils.java │ │ │ │ ├── Program.java │ │ │ │ ├── Rotation.java │ │ │ │ └── TextureRotationUtils.java │ │ │ └── res │ │ │ ├── layout │ │ │ └── customvideocaptureactivity_activity_custom_video_capture.xml │ │ │ ├── values-en │ │ │ └── strings.xml │ │ │ └── values │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── HlsAutoBitrate │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── tencent │ │ │ │ └── mlvb │ │ │ │ └── hlsautobitrate │ │ │ │ └── HlsAutoBitrateActivity.java │ │ │ └── res │ │ │ ├── layout │ │ │ └── hlsautobitrate_activity_hls_auto_bitrate.xml │ │ │ ├── values-en │ │ │ └── strings.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── LebAutoBitrate │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── tencent │ │ │ │ └── mlvb │ │ │ │ └── lebautobitrate │ │ │ │ └── LebAutoBitrateActivity.java │ │ │ └── res │ │ │ ├── layout │ │ │ └── lebautobitrate_activity_leb_auto_bitrate.xml │ │ │ ├── values-en │ │ │ └── strings.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── NewTimeShiftSprite │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── consumer-rules.pro │ │ ├── proguard-rules.pro │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── tencent │ │ │ │ └── mlvb │ │ │ │ └── newtimeshiftspriite │ │ │ │ ├── NewTimeShiftSpriteActivity.java │ │ │ │ └── TXSpriteImageFetcher.java │ │ │ └── res │ │ │ ├── layout │ │ │ └── activity_new_time_shift_sprite.xml │ │ │ ├── values-en │ │ │ └── strings.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── PictureInPicture │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── tencent │ │ │ │ └── mlvb │ │ │ │ └── pictureinpicture │ │ │ │ └── PictureInPictureActivity.java │ │ │ └── res │ │ │ ├── layout │ │ │ └── activity_picture_in_picture.xml │ │ │ ├── values-en │ │ │ └── strings.xml │ │ │ └── values │ │ │ ├── color.xml.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── RTCPushAndPlay │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── tencent │ │ │ │ └── mlvb │ │ │ │ └── rtcpushandplay │ │ │ │ ├── RTCPushAndPlayAnchorActivity.java │ │ │ │ ├── RTCPushAndPlayAudienceActivity.java │ │ │ │ └── RTCPushAndPlayEnterActivity.java │ │ │ └── res │ │ │ ├── layout │ │ │ ├── rtcpushandplay_activity_rtc_push_and_play_anchor.xml │ │ │ ├── rtcpushandplay_activity_rtc_push_and_play_audience.xml │ │ │ └── rtcpushandplay_activity_rtc_push_and_play_enter.xml │ │ │ ├── values-en │ │ │ └── strings.xml │ │ │ └── values │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── SwitchRenderView │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── tencent │ │ │ │ └── mlvb │ │ │ │ └── switchrenderview │ │ │ │ └── SwitchRenderViewActivity.java │ │ │ └── res │ │ │ ├── layout │ │ │ └── switchrenderview_activity_switch_render_view.xml │ │ │ ├── values-en │ │ │ └── strings.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── ThirdBeauty │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── tencent │ │ │ │ └── mlvb │ │ │ │ └── thirdbeauty │ │ │ │ ├── ThirdBeautyEntranceActivity.java │ │ │ │ ├── ThirdBeautyFaceUnityActivity.java │ │ │ │ └── ThirdBeautyTencentEffectActivity.java │ │ │ └── res │ │ │ ├── drawable │ │ │ └── button_bg.xml │ │ │ ├── layout │ │ │ ├── activity_third_beauty_entrance.xml │ │ │ ├── activity_third_beauty_tencent_effect.xml │ │ │ └── thirdbeauty_activity_third_beauty.xml │ │ │ ├── values-en │ │ │ └── strings.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ └── TimeShift │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── consumer-rules.pro │ │ ├── proguard-rules.pro │ │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── tencent │ │ │ └── mlvb │ │ │ └── timeshift │ │ │ ├── TimeShiftActivity.java │ │ │ └── TimeShiftHelper.java │ │ └── res │ │ ├── layout │ │ └── activity_time_shift.xml │ │ ├── values-en │ │ └── strings.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml ├── App │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── tencent │ │ │ └── mlvb │ │ │ └── apiexample │ │ │ ├── MLVBApplication.java │ │ │ └── MainActivity.java │ │ └── res │ │ ├── drawable │ │ ├── button_bg.xml │ │ └── ic_launcher.png │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_appicon.png │ │ ├── ic_launch_image.png │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-en │ │ └── strings.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml ├── Basic │ ├── LebPlay │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── tencent │ │ │ │ └── liteav │ │ │ │ └── sdk │ │ │ │ └── lebplay │ │ │ │ ├── LebPlayActivity.java │ │ │ │ └── LebPlayEnterActivity.java │ │ │ └── res │ │ │ ├── layout │ │ │ ├── lebplay_activity_leb_play.xml │ │ │ └── lebplay_activity_leb_play_enter.xml │ │ │ ├── values-en │ │ │ └── strings.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── LiveLink │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── tencent │ │ │ │ └── mlvb │ │ │ │ └── livelink │ │ │ │ ├── LiveLinkAnchorActivity.java │ │ │ │ ├── LiveLinkAudienceActivity.java │ │ │ │ └── LiveLinkEnterActivity.java │ │ │ └── res │ │ │ ├── drawable │ │ │ ├── livelink_selector_role_btn_bg.xml │ │ │ ├── livelink_start_link.png │ │ │ └── livelink_stop_link.png │ │ │ ├── layout │ │ │ ├── livelink_activity_live_link_anchor.xml │ │ │ ├── livelink_activity_live_link_audience.xml │ │ │ └── livelink_activity_live_link_enter.xml │ │ │ ├── values-en │ │ │ └── strings.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── LivePK │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── tencent │ │ │ │ └── mlvb │ │ │ │ └── linkpk │ │ │ │ ├── LivePKAnchorActivity.java │ │ │ │ ├── LivePKAudienceActivity.java │ │ │ │ └── LivePKEnterActivity.java │ │ │ └── res │ │ │ ├── drawable │ │ │ ├── livepk_selector_role_btn_bg.xml │ │ │ ├── livepk_start_link.png │ │ │ └── livepk_stop_link.png │ │ │ ├── layout │ │ │ ├── livepk_activity_live_pk_anchor.xml │ │ │ ├── livepk_activity_live_pk_audience.xml │ │ │ └── livepk_activity_live_pk_enter.xml │ │ │ ├── values-en │ │ │ └── strings.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── LivePlay │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── tencent │ │ │ │ └── mlvb │ │ │ │ └── liveplay │ │ │ │ ├── LivePlayActivity.java │ │ │ │ └── LivePlayEnterActivity.java │ │ │ └── res │ │ │ ├── layout │ │ │ ├── liveplay_activity_live_play.xml │ │ │ └── liveplay_activity_live_play_enter.xml │ │ │ ├── values-en │ │ │ └── strings.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── LivePushCamera │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── tencent │ │ │ │ └── mlvb │ │ │ │ └── livepushcamera │ │ │ │ ├── LivePushCameraActivity.java │ │ │ │ └── LivePushCameraEnterActivity.java │ │ │ └── res │ │ │ ├── drawable │ │ │ └── livepusher_content_bg.xml │ │ │ ├── layout │ │ │ ├── livepushcamera_activity_push_camera.xml │ │ │ └── livepushcamera_activity_push_camera_enter.xml │ │ │ ├── menu │ │ │ ├── livepushcamera_mirror.xml │ │ │ ├── livepushcamera_resolution.xml │ │ │ └── livepushcamera_rotate.xml │ │ │ ├── mipmap-xxhdpi │ │ │ ├── app_ic_bottom_camera_back.png │ │ │ ├── app_ic_bottom_camera_front.png │ │ │ ├── app_ic_bottom_mic_off.png │ │ │ ├── app_ic_bottom_mic_on.png │ │ │ ├── app_ic_close.png │ │ │ ├── app_ic_ic_back.png │ │ │ ├── app_ic_plus.png │ │ │ ├── app_ic_remote_video_off.png │ │ │ └── app_ic_remote_video_on.png │ │ │ ├── values-en │ │ │ └── strings.xml │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ └── LivePushScreen │ │ ├── .gitignore │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── tencent │ │ │ └── mlvb │ │ │ └── livepushscreen │ │ │ ├── LivePushScreenActivity.java │ │ │ └── LivePushScreenEnterActivity.java │ │ └── res │ │ ├── drawable │ │ └── livepusher_content_bg.xml │ │ ├── layout │ │ ├── livepushscreen_activity_push_screen.xml │ │ └── livepushscreen_activity_push_screen_enter.xml │ │ ├── values-en │ │ └── strings.xml │ │ └── values │ │ ├── strings.xml │ │ └── styles.xml ├── Common │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── tencent │ │ │ └── mlvb │ │ │ └── common │ │ │ ├── FlowRadioGroup.java │ │ │ ├── MLVBBaseActivity.java │ │ │ └── URLUtils.java │ │ └── res │ │ ├── drawable │ │ ├── common_arrow_above.png │ │ ├── common_button_bg.xml │ │ ├── common_button_grey_bg.xml │ │ ├── common_edit_bg.xml │ │ ├── common_ic_select_off.png │ │ ├── common_ic_select_on.png │ │ ├── common_rb_icon_selector.xml │ │ ├── common_seekbar_style.xml │ │ ├── common_seekbar_thumb.xml │ │ └── common_selector_radio_bg.xml │ │ ├── mipmap-xxhdpi │ │ ├── common_ic_back.png │ │ └── common_user_portrait.png │ │ ├── values-en │ │ └── strings.xml │ │ └── values │ │ ├── colors.xml │ │ └── strings.xml ├── Debug │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── tencent │ │ └── mlvb │ │ └── debug │ │ └── GenerateTestUserSig.java ├── README-zh_CN.md ├── README.md ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── README.md └── SDK ├── README-zh_CN.md └── README.md /MLVB-API-Example/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | *.gradle/ 3 | /local.properties 4 | *.idea/ 5 | .DS_Store 6 | /build 7 | /build.yml -------------------------------------------------------------------------------- /MLVB-API-Example/Advanced/CustomVideoCapture/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /MLVB-API-Example/Advanced/CustomVideoCapture/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion rootProject.ext.compileSdkVersion 5 | buildToolsVersion rootProject.ext.buildToolsVersion 6 | 7 | defaultConfig { 8 | minSdkVersion rootProject.ext.minSdkVersion 9 | targetSdkVersion rootProject.ext.targetSdkVersion 10 | versionCode 1 11 | versionName "1.0" 12 | ndk { 13 | abiFilters "armeabi-v7a", "arm64-v8a" 14 | } 15 | } 16 | 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | } 24 | 25 | dependencies { 26 | implementation fileTree(dir: "libs", include: ["*.jar"]) 27 | implementation rootProject.ext.liteavSdk 28 | implementation 'androidx.appcompat:appcompat:1.1.0' 29 | implementation project(':Debug') 30 | implementation project(':Common') 31 | } -------------------------------------------------------------------------------- /MLVB-API-Example/Advanced/CustomVideoCapture/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /MLVB-API-Example/Advanced/CustomVideoCapture/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /MLVB-API-Example/Advanced/CustomVideoCapture/src/main/java/com/tencent/mlvb/customvideocapture/helper/basic/Frame.java: -------------------------------------------------------------------------------- 1 | package com.tencent.mlvb.customvideocapture.helper.basic; 2 | 3 | import android.media.MediaCodec; 4 | import android.media.MediaCodec.BufferInfo; 5 | 6 | import java.nio.ByteBuffer; 7 | 8 | public class Frame { 9 | /** 10 | * The data contained in this frame, this buffer may be returned from {@link MediaCodec#getInputBuffers()}, 11 | * Needs to be returned to MediaCodec after use is completed. 12 | */ 13 | public ByteBuffer buffer; 14 | 15 | /** 16 | * If {@link Frame#buffer} is returned from another module, this member records its index. 17 | */ 18 | public int bufferIndex; 19 | 20 | /** 21 | * Identifies which byte in the cache starts to be valid data. 22 | */ 23 | public int offset; 24 | 25 | /** 26 | * Identifies the length of valid data in the cache. 27 | */ 28 | public int size; 29 | 30 | /** 31 | * The display time corresponding to this data 32 | */ 33 | public long presentationTimeUs; 34 | 35 | /** 36 | * Some flags, see {@link BufferInfo#flags} for details 37 | */ 38 | public int flags; 39 | } 40 | -------------------------------------------------------------------------------- /MLVB-API-Example/Advanced/CustomVideoCapture/src/main/java/com/tencent/mlvb/customvideocapture/helper/basic/FrameBuffer.java: -------------------------------------------------------------------------------- 1 | package com.tencent.mlvb.customvideocapture.helper.basic; 2 | 3 | import android.opengl.GLES20; 4 | import android.util.Log; 5 | 6 | import com.tencent.mlvb.customvideocapture.helper.render.opengl.OpenGlUtils; 7 | 8 | 9 | public class FrameBuffer { 10 | private static final String TAG = "FrameBuffer"; 11 | 12 | private final int mWidth; 13 | private final int mHeight; 14 | private int mTextureId; 15 | private int mFrameBufferId; 16 | 17 | public FrameBuffer(int width, int height) { 18 | mWidth = width; 19 | mHeight = height; 20 | } 21 | 22 | public void initialize() { 23 | mTextureId = OpenGlUtils.loadTexture(GLES20.GL_RGBA, null, mWidth, mHeight, OpenGlUtils.NO_TEXTURE); 24 | mFrameBufferId = OpenGlUtils.generateFrameBufferId(); 25 | Log.i(TAG, String.format("create frameBufferId: %d, textureId: %d", mFrameBufferId, mTextureId)); 26 | 27 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureId); 28 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBufferId); 29 | GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, 30 | GLES20.GL_TEXTURE_2D, mTextureId, 0); 31 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0); 32 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 33 | } 34 | 35 | public int getTextureId() { 36 | return mTextureId; 37 | } 38 | 39 | public int getFrameBufferId() { 40 | return mFrameBufferId; 41 | } 42 | 43 | public void uninitialize() { 44 | Log.i(TAG, String.format("destroy frameBufferId: %d, textureId: %d", mFrameBufferId, mTextureId)); 45 | OpenGlUtils.deleteTexture(mTextureId); 46 | mTextureId = OpenGlUtils.NO_TEXTURE; 47 | OpenGlUtils.deleteFrameBuffer(mFrameBufferId); 48 | mFrameBufferId = OpenGlUtils.NO_TEXTURE; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /MLVB-API-Example/Advanced/CustomVideoCapture/src/main/java/com/tencent/mlvb/customvideocapture/helper/basic/Size.java: -------------------------------------------------------------------------------- 1 | package com.tencent.mlvb.customvideocapture.helper.basic; 2 | 3 | public class Size { 4 | public int width; 5 | public int height; 6 | 7 | public Size() { 8 | } 9 | 10 | public Size(int width, int height) { 11 | this.width = width; 12 | this.height = height; 13 | } 14 | 15 | @SuppressWarnings("SuspiciousNameCombination") 16 | public void swap() { 17 | int temp = width; 18 | width = height; 19 | height = temp; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /MLVB-API-Example/Advanced/CustomVideoCapture/src/main/java/com/tencent/mlvb/customvideocapture/helper/basic/TextureFrame.java: -------------------------------------------------------------------------------- 1 | package com.tencent.mlvb.customvideocapture.helper.basic; 2 | 3 | import android.opengl.EGLContext; 4 | 5 | public class TextureFrame { 6 | public EGLContext eglContext; 7 | 8 | public int textureId; 9 | 10 | public int width; 11 | 12 | public int height; 13 | 14 | public long timestampMs; 15 | } 16 | -------------------------------------------------------------------------------- /MLVB-API-Example/Advanced/CustomVideoCapture/src/main/java/com/tencent/mlvb/customvideocapture/helper/render/EGLHelper.java: -------------------------------------------------------------------------------- 1 | package com.tencent.mlvb.customvideocapture.helper.render; 2 | 3 | /** 4 | * Android has two sets of EGL classes. 5 | * For convenience of use, they are abstracted and only the following interfaces are provided. 6 | * 7 | * @param 8 | */ 9 | public interface EGLHelper { 10 | /** 11 | * Returns EGLContext, used to create shared EGLContext, etc. 12 | */ 13 | T getContext(); 14 | 15 | /** 16 | * Bind EGLContext to the current thread, as well as the draw Surface and read Surface saved in Helper. 17 | */ 18 | void makeCurrent(); 19 | 20 | /** 21 | * Unbind the EGLContext, draw Surface, and read Surface bound to the current thread. 22 | */ 23 | void unmakeCurrent(); 24 | 25 | /** 26 | * Brush rendered content onto the bound draw target. 27 | */ 28 | boolean swapBuffers(); 29 | 30 | /** 31 | * Destroy the created EGLContext and related resources. 32 | */ 33 | void destroy(); 34 | } 35 | -------------------------------------------------------------------------------- /MLVB-API-Example/Advanced/CustomVideoCapture/src/main/java/com/tencent/mlvb/customvideocapture/helper/render/EglCore.java: -------------------------------------------------------------------------------- 1 | package com.tencent.mlvb.customvideocapture.helper.render; 2 | 3 | import android.annotation.TargetApi; 4 | import android.view.Surface; 5 | 6 | /** 7 | * When eglMakeCurrent, you need to associate the Context and the window (or Surface), so combine the two. 8 | */ 9 | public class EglCore { 10 | private EGLHelper mEglHelper; 11 | 12 | /** 13 | * Create an EglCore, in which the window is an off-screen Surface and does not share other EGLContext 14 | * 15 | * @param width The width of the off-screen Surface 16 | * @param height The height of the off-screen Surface 17 | */ 18 | public EglCore(int width, int height) { 19 | this((android.opengl.EGLContext) null, width, height); 20 | } 21 | 22 | /** 23 | * Create an EglCore, the window is the incoming Surface, and do not share other EGLContext 24 | * 25 | * @param surface The rendering target of the newly created EGLContext 26 | */ 27 | public EglCore(Surface surface) { 28 | this((android.opengl.EGLContext) null, surface); 29 | } 30 | 31 | /** 32 | * Create an EglCore and associate it with an off-screen surface 33 | * 34 | * @param sharedContext used for shared OpenGL Context, can be null 35 | * @param width The width of the off-screen surface 36 | * @param height The height of the off-screen surface 37 | */ 38 | public EglCore(android.opengl.EGLContext sharedContext, int width, int height) { 39 | mEglHelper = EGL14Helper.createEGLSurface(null, sharedContext, null, width, height); 40 | } 41 | 42 | /** 43 | * Create an EglCore and associate it with an off-screen surface 44 | * 45 | * @param sharedContext used for shared OpenGL Context, can be null 46 | * @param width The width of the off-screen surface 47 | * @param height The height of the off-screen surface 48 | */ 49 | public EglCore(javax.microedition.khronos.egl.EGLContext sharedContext, int width, int height) { 50 | mEglHelper = EGL10Helper.createEGLSurface(null, sharedContext, null, width, height); 51 | } 52 | 53 | /** 54 | * Create an EglCore and associate it with the incoming surface 55 | * 56 | * @param sharedContext used for shared OpenGL Context, can be null 57 | * @param surface rendering target 58 | */ 59 | public EglCore(android.opengl.EGLContext sharedContext, Surface surface) { 60 | mEglHelper = EGL14Helper.createEGLSurface(null, sharedContext, surface, 0, 0); 61 | } 62 | 63 | /** 64 | * Create an EglCore and associate it with the incoming surface 65 | * 66 | * @param sharedContext used for shared OpenGL Context, can be null 67 | * @param surface rendering target 68 | */ 69 | public EglCore(javax.microedition.khronos.egl.EGLContext sharedContext, Surface surface) { 70 | mEglHelper = EGL10Helper.createEGLSurface(null, sharedContext, surface, 0, 0); 71 | } 72 | 73 | public void makeCurrent() { 74 | mEglHelper.makeCurrent(); 75 | } 76 | 77 | public void unmakeCurrent() { 78 | mEglHelper.unmakeCurrent(); 79 | } 80 | 81 | public void swapBuffer() { 82 | mEglHelper.swapBuffers(); 83 | } 84 | 85 | public Object getEglContext() { 86 | return mEglHelper.getContext(); 87 | } 88 | 89 | public void destroy() { 90 | mEglHelper.destroy(); 91 | mEglHelper = null; 92 | } 93 | 94 | @TargetApi(18) 95 | public void setPresentationTime(long nsecs) { 96 | if (mEglHelper instanceof EGL14Helper) { 97 | ((EGL14Helper) mEglHelper).setPresentationTime(nsecs); 98 | } 99 | } 100 | } 101 | 102 | -------------------------------------------------------------------------------- /MLVB-API-Example/Advanced/CustomVideoCapture/src/main/java/com/tencent/mlvb/customvideocapture/helper/render/opengl/OesInputFilter.java: -------------------------------------------------------------------------------- 1 | package com.tencent.mlvb.customvideocapture.helper.render.opengl; 2 | 3 | import android.opengl.GLES11Ext; 4 | import android.opengl.GLES20; 5 | 6 | public class OesInputFilter extends GPUImageFilter { 7 | private static final String OES_INPUT_VERTEX_SHADER = "" 8 | + "attribute vec4 position;\n" 9 | + "attribute vec4 inputTextureCoordinate;\n" 10 | + "uniform mat4 textureTransform;\n" 11 | + "\n" 12 | + "varying highp vec2 textureCoordinate;\n" 13 | + "void main()\n" 14 | + "{\n" 15 | + " gl_Position = position;\n" 16 | + " textureCoordinate = (textureTransform * inputTextureCoordinate).xy;\n" 17 | + "}\n"; 18 | 19 | private static final String OES_INPUT_FRAGMENT_SHADER = "" 20 | + "#extension GL_OES_EGL_image_external : require\n" 21 | + "precision mediump float;\n" 22 | + "varying highp vec2 textureCoordinate;\n" 23 | + " \n" 24 | + "uniform samplerExternalOES inputImageTexture;\n" 25 | + " \n" 26 | + "void main()\n" 27 | + "{\n" 28 | + " gl_FragColor = texture2D(inputImageTexture, textureCoordinate);\n" 29 | + "}"; 30 | 31 | protected int mTextureTransform; 32 | 33 | public OesInputFilter() { 34 | super(OES_INPUT_VERTEX_SHADER, OES_INPUT_FRAGMENT_SHADER); 35 | } 36 | 37 | public OesInputFilter(final String vertexShader, final String fragmentShader) { 38 | super(vertexShader, fragmentShader); 39 | } 40 | 41 | @Override 42 | public int getTarget() { 43 | return GLES11Ext.GL_TEXTURE_EXTERNAL_OES; 44 | } 45 | 46 | @Override 47 | public void onInit() { 48 | super.onInit(); 49 | mTextureTransform = GLES20.glGetUniformLocation(mProgram.getProgramId(), "textureTransform"); 50 | } 51 | 52 | @Override 53 | protected void beforeDrawArrays(int textureId) { 54 | super.beforeDrawArrays(textureId); 55 | GLES20.glUniformMatrix4fv(mTextureTransform, 1, false, mTextureMatrix, 0); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /MLVB-API-Example/Advanced/CustomVideoCapture/src/main/java/com/tencent/mlvb/customvideocapture/helper/render/opengl/Program.java: -------------------------------------------------------------------------------- 1 | package com.tencent.mlvb.customvideocapture.helper.render.opengl; 2 | 3 | import android.opengl.GLES20; 4 | import android.util.Log; 5 | 6 | public class Program { 7 | private static final String TAG = "Program"; 8 | private static final int INVALID_PROGRAM_ID = -1; 9 | 10 | private final String mVertexShader; 11 | private final String mFragmentShader; 12 | private int mProgramId; 13 | 14 | public Program(String vertexShader, String fragmentShader) { 15 | mVertexShader = vertexShader; 16 | mFragmentShader = fragmentShader; 17 | mProgramId = INVALID_PROGRAM_ID; 18 | } 19 | 20 | /** 21 | * create programId 。 22 | */ 23 | public void build() { 24 | int vertexShaderId = loadShader(mVertexShader, GLES20.GL_VERTEX_SHADER); 25 | if (vertexShaderId == 0) { 26 | Log.e(TAG, "load vertex shader failed."); 27 | return; 28 | } 29 | 30 | int fragmentShaderId = loadShader(mFragmentShader, GLES20.GL_FRAGMENT_SHADER); 31 | if (fragmentShaderId == 0) { 32 | Log.e(TAG, "load fragment shader failed."); 33 | return; 34 | } 35 | 36 | int programId = GLES20.glCreateProgram(); 37 | GLES20.glAttachShader(programId, vertexShaderId); 38 | GLES20.glAttachShader(programId, fragmentShaderId); 39 | GLES20.glLinkProgram(programId); 40 | 41 | int[] link = new int[1]; 42 | GLES20.glGetProgramiv(programId, GLES20.GL_LINK_STATUS, link, 0); 43 | if (link[0] <= 0) { 44 | Log.e(TAG, "link program failed. status: " + link[0]); 45 | return; 46 | } 47 | 48 | GLES20.glDeleteShader(vertexShaderId); 49 | GLES20.glDeleteShader(fragmentShaderId); 50 | mProgramId = programId; 51 | } 52 | 53 | public int getProgramId() { 54 | return mProgramId; 55 | } 56 | 57 | public void destroy() { 58 | GLES20.glDeleteProgram(mProgramId); 59 | mProgramId = INVALID_PROGRAM_ID; 60 | } 61 | 62 | private int loadShader(final String strSource, final int iType) { 63 | int[] compiled = new int[1]; 64 | int iShader = GLES20.glCreateShader(iType); 65 | GLES20.glShaderSource(iShader, strSource); 66 | GLES20.glCompileShader(iShader); 67 | GLES20.glGetShaderiv(iShader, GLES20.GL_COMPILE_STATUS, compiled, 0); 68 | if (compiled[0] == 0) { 69 | OpenGlUtils.checkGlError("glCompileShader"); 70 | return 0; 71 | } 72 | return iShader; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /MLVB-API-Example/Advanced/CustomVideoCapture/src/main/java/com/tencent/mlvb/customvideocapture/helper/render/opengl/Rotation.java: -------------------------------------------------------------------------------- 1 | package com.tencent.mlvb.customvideocapture.helper.render.opengl; 2 | 3 | public enum Rotation { 4 | NORMAL, ROTATION_90, ROTATION_180, ROTATION_270; 5 | 6 | /** 7 | * Create a Rotation from an integer. Needs to be either 0, 90, 180 or 270. 8 | * 9 | * @param rotation 0, 90, 180 or 270 10 | * @return Rotation object 11 | */ 12 | public static Rotation fromInt(int rotation) { 13 | switch (rotation) { 14 | case 0: 15 | return NORMAL; 16 | case 90: 17 | return ROTATION_90; 18 | case 180: 19 | return ROTATION_180; 20 | case 270: 21 | return ROTATION_270; 22 | case 360: 23 | return NORMAL; 24 | default: 25 | return NORMAL; 26 | } 27 | } 28 | 29 | /** 30 | * Retrieves the int representation of the Rotation. 31 | * 32 | * @return 0, 90, 180 or 270 33 | */ 34 | public int asInt() { 35 | switch (this) { 36 | case NORMAL: 37 | return 0; 38 | case ROTATION_90: 39 | return 90; 40 | case ROTATION_180: 41 | return 180; 42 | case ROTATION_270: 43 | return 270; 44 | default: 45 | return 0; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /MLVB-API-Example/Advanced/CustomVideoCapture/src/main/java/com/tencent/mlvb/customvideocapture/helper/render/opengl/TextureRotationUtils.java: -------------------------------------------------------------------------------- 1 | package com.tencent.mlvb.customvideocapture.helper.render.opengl; 2 | 3 | public class TextureRotationUtils { 4 | public static final float[] TEXTURE_NO_ROTATION = {0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f}; 5 | public static final float[] TEXTURE_ROTATED_90 = {1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}; 6 | public static final float[] TEXTURE_ROTATED_180 = {1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f}; 7 | public static final float[] TEXTURE_ROTATED_270 = {0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f}; 8 | 9 | private TextureRotationUtils() { 10 | } 11 | 12 | /** 13 | * Gets the rotation direction of the Texture. 14 | */ 15 | public static float[] getRotation(final Rotation rotation, 16 | final boolean flipHorizontal, 17 | final boolean flipVertical) { 18 | float[] rotatedTex; 19 | switch (rotation) { 20 | case ROTATION_90: 21 | rotatedTex = TEXTURE_ROTATED_90; 22 | break; 23 | case ROTATION_180: 24 | rotatedTex = TEXTURE_ROTATED_180; 25 | break; 26 | case ROTATION_270: 27 | rotatedTex = TEXTURE_ROTATED_270; 28 | break; 29 | case NORMAL: 30 | default: 31 | rotatedTex = TEXTURE_NO_ROTATION; 32 | break; 33 | } 34 | 35 | if (flipHorizontal) { 36 | rotatedTex = new float[]{ 37 | flip(rotatedTex[0]), rotatedTex[1], 38 | flip(rotatedTex[2]), rotatedTex[3], 39 | flip(rotatedTex[4]), rotatedTex[5], 40 | flip(rotatedTex[6]), rotatedTex[7]}; 41 | } 42 | if (flipVertical) { 43 | rotatedTex = new float[]{ 44 | rotatedTex[0], flip(rotatedTex[1]), 45 | rotatedTex[2], flip(rotatedTex[3]), 46 | rotatedTex[4], flip(rotatedTex[5]), 47 | rotatedTex[6], flip(rotatedTex[7])}; 48 | } 49 | return rotatedTex; 50 | } 51 | 52 | private static float flip(final float i) { 53 | if (i == 0.0f) { 54 | return 1.0f; 55 | } 56 | return 0.0f; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /MLVB-API-Example/Advanced/CustomVideoCapture/src/main/res/layout/customvideocaptureactivity_activity_custom_video_capture.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 15 | 16 | 23 | 24 | 32 | 33 | 34 | 41 | 42 | 47 | 48 | 54 | 55 | 63 | 64 | 65 |