安卓虚拟相机虚拟摄像头插件,IOS苹果iphone,微信QQ都支持,提供dex\hook类代码

这篇具有很好参考价值的文章主要介绍了安卓虚拟相机虚拟摄像头插件,IOS苹果iphone,微信QQ都支持,提供dex\hook类代码。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

核心HOOK思路源码开源了,仅供学习,用的一个java类实现的,但是成品我不提供奥,就提供下实现虚拟视频hook类的java代码【我已经把dex文件里面实现hook的字节码代码转换成java代码了】,仅供大家研究,用工具是Smali将字节码代码转换为Java代码,工具下面地址可以自己网上搜。

开源虚拟摄像头,ios,android,数码相机

下面是我测试一个效果视频【仅供学习】: 

虚拟摄像头插件,玩玩,支持微信QQ,替换摄像头,还是开源的!!!

下面是实现HOOk的java代码,我已经用Smali导出来了:

===================================================================

//

// Decompiled by Jadx - 791ms

//

package com.exampsle.vcam;

import android.graphics.ImageFormat;

import android.graphics.Rect;

import android.media.Image;

import android.media.MediaCodec;

import android.media.MediaCodecInfo;

import android.media.MediaCrypto;

import android.media.MediaExtractor;

import android.media.MediaFormat;

import android.util.Log;

import android.view.Surface;

import de.robv.android.xposed.XposedBridge;

import java.io.File;

import java.io.IOException;

import java.io.PrintStream;

import java.nio.ByteBuffer;

import java.util.concurrent.LinkedBlockingQueue;

public class VideoToFrames implements Runnable {

    private static final int COLOR_FormatI420 = 1;

    private static final int COLOR_FormatNV21 = 2;

    private static final long DEFAULT_TIMEOUT_US = 10000;

    private static final String TAG = "VideoToFrames";

    private static final boolean VERBOSE = false;

    private Callback callback;

    private Thread childThread;

    private LinkedBlockingQueue<byte[]> mQueue;

    private OutputImageFormat outputImageFormat;

    private Surface play_surf;

    private Throwable throwable;

    private String videoFilePath;

    private final int decodeColorFormat = 0x7f420888;

    private boolean stopDecode = false;

    public void setCallback(Callback callback) {

        this.callback = callback;

    }

    public void setEnqueue(LinkedBlockingQueue<byte[]> linkedBlockingQueue) {

        this.mQueue = linkedBlockingQueue;

    }

    public void setSaveFrames(String str, OutputImageFormat outputImageFormat) throws IOException {

        this.outputImageFormat = outputImageFormat;

    }

    public void set_surfcae(Surface surface) {

        if (surface != null) {

            this.play_surf = surface;

        }

    }

    public void stopDecode() {

        this.stopDecode = true;

    }

    public void decode(String str) throws Throwable {

        this.videoFilePath = str;

        if (this.childThread == null) {

            Thread thread = new Thread(this, "decode");

            this.childThread = thread;

            thread.start();

            Throwable th = this.throwable;

            if (th != null) {

                throw th;

            }

        }

    }

    @Override

    public void run() {

        try {

            videoDecode(this.videoFilePath);

        } catch (Throwable th) {

            this.throwable = th;

        }

    }

    /* JADX WARN: Multi-variable type inference failed */

    /* JADX WARN: Removed duplicated region for block: B:32:0x00c1  */

    /* JADX WARN: Removed duplicated region for block: B:34:0x00c9  */

    /* JADX WARN: Type inference failed for: r0v1, types: [android.media.MediaCodec, android.media.MediaExtractor] */

    /* JADX WARN: Type inference failed for: r0v3 */

    /* JADX WARN: Type inference failed for: r0v4, types: [android.media.MediaCodec] */

    /* JADX WARN: Type inference failed for: r0v5 */

    /*

        Code decompiled incorrectly, please refer to instructions dump.

    */

    public void videoDecode(String str) throws IOException {

        MediaExtractor mediaExtractor;

        XposedBridge.log("【VCAM】【decoder】开始解码");

        MediaCodec mediaCodec = 0;

        mediaCodec = 0;

        try {

            try {

                new File(str);

                mediaExtractor = new MediaExtractor();

                try {

                    mediaExtractor.setDataSource(str);

                    int selectTrack = selectTrack(mediaExtractor);

                    if (selectTrack < 0) {

                        XposedBridge.log("【VCAM】【decoder】No video track found in " + str);

                    }

                    mediaExtractor.selectTrack(selectTrack);

                    MediaFormat trackFormat = mediaExtractor.getTrackFormat(selectTrack);

                    String string = trackFormat.getString("mime");

                    mediaCodec = MediaCodec.createDecoderByType(string);

                    showSupportedColorFormat(mediaCodec.getCodecInfo().getCapabilitiesForType(string));

                    if (isColorFormatSupported(0x7f420888, mediaCodec.getCodecInfo().getCapabilitiesForType(string))) {

                        trackFormat.setInteger("color-format", 0x7f420888);

                        XposedBridge.log("【VCAM】【decoder】set decode color format to type 2135033992");

                    } else {

                        Log.i(TAG, "unable to set decode color format, color format type 0x7f420888 not supported");

                        XposedBridge.log("【VCAM】【decoder】unable to set decode color format, color format type 0x7f420888 not supported");

                    }

                    decodeFramesToImage(mediaCodec, mediaExtractor, trackFormat);

                    mediaCodec.stop();

                    while (!this.stopDecode) {

                        mediaExtractor.seekTo(0L, 0);

                        decodeFramesToImage(mediaCodec, mediaExtractor, trackFormat);

                        mediaCodec.stop();

                    }

                    if (mediaCodec != 0) {

                        mediaCodec.stop();

                        mediaCodec.release();

                    }

                } catch (Exception e) {

                    e = e;

                    XposedBridge.log("【VCAM】[videofile]" + e.toString());

                    if (mediaCodec != 0) {

                        mediaCodec.stop();

                        mediaCodec.release();

                    }

                    if (mediaExtractor == null) {

                        return;

                    }

                    mediaExtractor.release();

                }

            } catch (Throwable th) {

                th = th;

                if (0 != 0) {

                    mediaCodec.stop();

                    mediaCodec.release();

                }

                if (0 != 0) {

                    mediaCodec.release();

                }

                throw th;

            }

        } catch (Exception e2) {

            e = e2;

            mediaExtractor = null;

        } catch (Throwable th2) {

            th = th2;

            if (0 != 0) {

            }

            if (0 != 0) {

            }

            throw th;

        }

        mediaExtractor.release();

    }

    private void showSupportedColorFormat(MediaCodecInfo.CodecCapabilities codecCapabilities) {

        System.out.print("supported color format: ");

        int[] iArr = codecCapabilities.colorFormats;

        int length = iArr.length;

        for (int i = 0; i < length; i += COLOR_FormatI420) {

            int i2 = iArr[i];

            PrintStream printStream = System.out;

            printStream.print(i2 + "\t");

        }

        System.out.println();

    }

    private boolean isColorFormatSupported(int i, MediaCodecInfo.CodecCapabilities codecCapabilities) {

        int[] iArr = codecCapabilities.colorFormats;

        int length = iArr.length;

        for (int i2 = 0; i2 < length; i2 += COLOR_FormatI420) {

            if (iArr[i2] == i) {

                return true;

            }

        }

        return false;

    }

    private void decodeFramesToImage(MediaCodec mediaCodec, MediaExtractor mediaExtractor, MediaFormat mediaFormat) {

        long j;

        int dequeueInputBuffer;

        MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();

        mediaCodec.configure(mediaFormat, this.play_surf, (MediaCrypto) null, 0);

        mediaCodec.start();

        mediaFormat.getInteger("width");

        mediaFormat.getInteger("height");

        boolean z = false;

        boolean z2 = false;

        int i = 0;

        boolean z3 = false;

        long j2 = 0;

        while (!z && !this.stopDecode) {

            if (z2 || (dequeueInputBuffer = mediaCodec.dequeueInputBuffer(DEFAULT_TIMEOUT_US)) < 0) {

                j = 10000;

            } else {

                int readSampleData = mediaExtractor.readSampleData(mediaCodec.getInputBuffer(dequeueInputBuffer), 0);

                if (readSampleData < 0) {

                    j = 10000;

                    z2 = true;

                    mediaCodec.queueInputBuffer(dequeueInputBuffer, 0, 0, 0L, 4);

                } else {

                    j = 10000;

                    mediaCodec.queueInputBuffer(dequeueInputBuffer, 0, readSampleData, mediaExtractor.getSampleTime(), 0);

                    mediaExtractor.advance();

                }

            }

            int dequeueOutputBuffer = mediaCodec.dequeueOutputBuffer(bufferInfo, j);

            if (dequeueOutputBuffer >= 0) {

                boolean z4 = (bufferInfo.flags & 4) != 0 ? true : z;

                if (bufferInfo.size != 0) {

                    i += COLOR_FormatI420;

                    Callback callback = this.callback;

                    if (callback != null) {

                        callback.onDecodeFrame(i);

                    }

                    if (!z3) {

                        j2 = System.currentTimeMillis();

                        z3 = true;

                    }

                    if (this.play_surf == null) {

                        Image outputImage = mediaCodec.getOutputImage(dequeueOutputBuffer);

                        ByteBuffer buffer = outputImage.getPlanes()[0].getBuffer();

                        byte[] bArr = new byte[buffer.remaining()];

                        buffer.get(bArr);

                        LinkedBlockingQueue<byte[]> linkedBlockingQueue = this.mQueue;

                        if (linkedBlockingQueue != null) {

                            try {

                                linkedBlockingQueue.put(bArr);

                            } catch (InterruptedException e) {

                                XposedBridge.log("【VCAM】" + e.toString());

                            }

                        }

                        if (this.outputImageFormat != null) {

                            HookMain.data_buffer = getDataFromImage(outputImage, COLOR_FormatNV21);

                        }

                        outputImage.close();

                    }

                    long currentTimeMillis = (bufferInfo.presentationTimeUs / 1000) - (System.currentTimeMillis() - j2);

                    if (currentTimeMillis > 0) {

                        try {

                            Thread.sleep(currentTimeMillis);

                        } catch (InterruptedException e2) {

                            XposedBridge.log("【VCAM】" + e2.toString());

                            XposedBridge.log("【VCAM】线程延迟出错");

                        }

                    }

                    mediaCodec.releaseOutputBuffer(dequeueOutputBuffer, true);

                }

                z = z4;

            }

        }

        Callback callback2 = this.callback;

        if (callback2 != null) {

            callback2.onFinishDecode();

        }

    }

    private static int selectTrack(MediaExtractor mediaExtractor) {

        int trackCount = mediaExtractor.getTrackCount();

        for (int i = 0; i < trackCount; i += COLOR_FormatI420) {

            if (mediaExtractor.getTrackFormat(i).getString("mime").startsWith("video/")) {

                return i;

            }

        }

        return -1;

    }

    private static boolean isImageFormatSupported(Image image) {

        int format = image.getFormat();

        return format == 17 || format == 35 || format == 0x32315659;

    }

    /* JADX WARN: Removed duplicated region for block: B:30:0x007a  */

    /* JADX WARN: Removed duplicated region for block: B:31:0x007d  */

    /* JADX WARN: Removed duplicated region for block: B:34:0x0098  */

    /*

        Code decompiled incorrectly, please refer to instructions dump.

    */

    private static byte[] getDataFromImage(Image image, int i) {

        int i2;

        int i3;

        Rect rect;

        int i4;

        int i5 = i;

        int i6 = COLOR_FormatNV21;

        int i7 = COLOR_FormatI420;

        if (i5 != COLOR_FormatI420 && i5 != COLOR_FormatNV21) {

            throw new IllegalArgumentException("only support COLOR_FormatI420 and COLOR_FormatNV21");

        }

        if (!isImageFormatSupported(image)) {

            throw new RuntimeException("can't convert Image to byte array, format " + image.getFormat());

        }

        Rect cropRect = image.getCropRect();

        int format = image.getFormat();

        int width = cropRect.width();

        int height = cropRect.height();

        Image.Plane[] planes = image.getPlanes();

        int i8 = width * height;

        byte[] bArr = new byte[(ImageFormat.getBitsPerPixel(format) * i8) / 8];

        byte[] bArr2 = new byte[planes[0].getRowStride()];

        int i9 = 0;

        int i10 = 0;

        int i11 = COLOR_FormatI420;

        while (i9 < planes.length) {

            if (i9 == 0) {

                i10 = 0;

            } else if (i9 != i7) {

                if (i9 == i6) {

                    if (i5 == i7) {

                        i10 = (int) (i8 * 1.25d);

                    } else if (i5 == i6) {

                        i10 = i8;

                        i11 = COLOR_FormatNV21;

                    }

                }

                ByteBuffer buffer = planes[i9].getBuffer();

                int rowStride = planes[i9].getRowStride();

                int pixelStride = planes[i9].getPixelStride();

                int i12 = i9 == 0 ? 0 : COLOR_FormatI420;

                int i13 = width >> i12;

                i2 = height >> i12;

                int i14 = width;

                buffer.position(((cropRect.top >> i12) * rowStride) + ((cropRect.left >> i12) * pixelStride));

                i3 = 0;

                while (i3 < i2) {

                    if (pixelStride == COLOR_FormatI420 && i11 == COLOR_FormatI420) {

                        buffer.get(bArr, i10, i13);

                        i10 += i13;

                        rect = cropRect;

                        i4 = i13;

                    } else {

                        rect = cropRect;

                        i4 = ((i13 - 1) * pixelStride) + COLOR_FormatI420;

                        buffer.get(bArr2, 0, i4);

                        for (int i15 = 0; i15 < i13; i15 += COLOR_FormatI420) {

                            bArr[i10] = bArr2[i15 * pixelStride];

                            i10 += i11;

                        }

                    }

                    if (i3 < i2 - 1) {

                        buffer.position((buffer.position() + rowStride) - i4);

                    }

                    i3 += COLOR_FormatI420;

                    cropRect = rect;

                }

                i9 += COLOR_FormatI420;

                i5 = i;

                width = i14;

                i6 = COLOR_FormatNV21;

                i7 = COLOR_FormatI420;

            } else if (i5 == i7) {

                i10 = i8;

            } else {

                if (i5 == i6) {

                    i10 = i8 + COLOR_FormatI420;

                    i11 = COLOR_FormatNV21;

                }

                ByteBuffer buffer2 = planes[i9].getBuffer();

                int rowStride2 = planes[i9].getRowStride();

                int pixelStride2 = planes[i9].getPixelStride();

                if (i9 == 0) {

                }

                int i132 = width >> i12;

                i2 = height >> i12;

                int i142 = width;

                buffer2.position(((cropRect.top >> i12) * rowStride2) + ((cropRect.left >> i12) * pixelStride2));

                i3 = 0;

                while (i3 < i2) {

                }

                i9 += COLOR_FormatI420;

                i5 = i;

                width = i142;

                i6 = COLOR_FormatNV21;

                i7 = COLOR_FormatI420;

            }

            i11 = COLOR_FormatI420;

            ByteBuffer buffer22 = planes[i9].getBuffer();

            int rowStride22 = planes[i9].getRowStride();

            int pixelStride22 = planes[i9].getPixelStride();

            if (i9 == 0) {

            }

            int i1322 = width >> i12;

            i2 = height >> i12;

            int i1422 = width;

            buffer22.position(((cropRect.top >> i12) * rowStride22) + ((cropRect.left >> i12) * pixelStride22));

            i3 = 0;

            while (i3 < i2) {

            }

            i9 += COLOR_FormatI420;

            i5 = i;

            width = i1422;

            i6 = COLOR_FormatNV21;

            i7 = COLOR_FormatI420;

        }

        return bArr;

    }

}

================================================================= 文章来源地址https://www.toymoban.com/news/detail-795757.html

到了这里,关于安卓虚拟相机虚拟摄像头插件,IOS苹果iphone,微信QQ都支持,提供dex\hook类代码的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android相机调用-CameraX【外接摄像头】【USB摄像头】

    Android相机调用有原生的Camera和Camera2,我觉得调用代码都太复杂了,CameraX调用代码简洁很多。 说明文档:https://developer.android.com/jetpack/androidx/releases/camera?hl=zh-cn 现有查到的调用资料都不够新,对于外接摄像头(USB摄像头)这类非前置也非后置摄像头的设备调用,都说是没有实

    2024年02月09日
    浏览(55)
  • 电脑上虚拟摄像头在哪关闭?多种方法关闭虚拟摄像头

    在数字化时代,虚拟摄像头成为了许多工作和娱乐场景中的必备工具。它允许我们在不使用物理摄像头的情况下,通过软件模拟摄像头功能,从而满足视频通话、直播、教学等多种需求。 然而,有时我们可能需要在某些情况下关闭虚拟摄像头,那么,电脑上虚拟摄像头应该在

    2024年04月12日
    浏览(51)
  • 安卓调用手机摄像头和相册

    新建一个CameraAlbumTest项目,修改activity_main.xml中的代码 可以看到在布局文件当中,有一个Button和一个ImageView.Button是用于打开摄像头进行拍照的,而ImageView则是用于将拍到图片显示出来. 在MainActivity中编写调用摄像头的代码逻辑 首先创建了一个File对象,用于存储摄像头拍下的图片

    2024年02月09日
    浏览(62)
  • Unity3D:调用安卓摄像头拍照

    操作步骤:创建脚步并挂载到Main Camera上 仍未解决的问题:导入到安卓平台测试时,拍照按钮不能随着屏幕旋转而变换位置; 拍照时会把拍照按钮也截进去。

    2024年02月06日
    浏览(51)
  • OpenCV开发笔记(七十七):相机标定(二):通过棋盘标定计算相机内参矩阵矫正畸变摄像头图像

    若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/136616551 各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究 红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、

    2024年03月13日
    浏览(48)
  • 将运动相机作为电脑摄像头 - 以Windows+SJCAM C100+为例

    确保相机是 关机状态 (因为接下来要取出SD卡,为保证数据安全)。 取出SD卡。 SD卡会让你的电脑认为它是U盘,所以不需要SD卡。 注意: SD卡移除的方式是按压弹出。 使用MicroUSB线连接你的电脑。 打开Windows自带的相机app。 等待显示画面。 看不懂的可以直接参考这个视频:

    2024年02月16日
    浏览(78)
  • windows驱动开发8:虚拟摄像头方案

    一、摄像头框架 在业务场景中,有许多是需要应用能够通过摄像头的方式来访问相关的音视频数据,比如美颜、摄像头多路复用、IP摄像头接入视频会议等。这些功能通过虚拟摄像头的方式来实现,是一个比较通用的解决方案。那么如何及选用哪种技术方案来开发虚拟摄像头

    2024年02月02日
    浏览(43)
  • 怎么让电脑上的摄像头无绿幕使用背景虚化/虚拟背景、视频无绿幕使用背景虚化、虚拟摄像头无绿幕背景虚化

    参考: https://github.com/aisegmentcn/aisegment_obs_plugin https://obsproject.com/forum/resources/virtual-background-by-aisegment.1546/ 腾讯会议中是可以使用虚拟背景的,但是其他视频会议软件没有,那怎么办 1. 下载OBS 打开steam,搜索OBS,我成功的这个OBS版本为30.0.2 2. 下载OBS AI虚拟背景插件 https://git

    2024年04月26日
    浏览(42)
  • ubuntu20.04下的USB摄像头使用与标定(单目相机)一.使用

    A.查找摄像头接口 B.在该路径下修改launch文件,换成你自己的摄像头接口 C.运行摄像头节点(此时就能看到画面了) ⭐可能会出现的错误 1.终端会warning是因为还没有进行摄像头标定,后续会进行讲解 2.若用的是虚拟机但发出了error,看看你的usb是接入3.0还是2.0处,然后在如下

    2024年02月04日
    浏览(170)
  • Android中相机(Camera)画面旋转角度分析:手机摄像头的“正向”、手机画面自然方向、相机画面的偏转角度

    #.概述:     1.如同人眼看东西分上下一样,摄像头也有其“正向”,正常情况下,Android手机后置、前置摄像头的“正向”朝向为手机的“右侧”(默认如此,除非手机厂商修改设置)。 (这里运行代码做过测试发现,前置摄像头也是以右侧为正向,而不是有些资料上说的

    2024年02月14日
    浏览(81)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包