核心HOOK思路源碼開源了,僅供學(xué)習(xí),用的一個java類實(shí)現(xiàn)的,但是成品我不提供奧,就提供下實(shí)現(xiàn)虛擬視頻hook類的java代碼【我已經(jīng)把dex文件里面實(shí)現(xiàn)hook的字節(jié)碼代碼轉(zhuǎn)換成java代碼了】,僅供大家研究,用工具是Smali將字節(jié)碼代碼轉(zhuǎn)換為Java代碼,工具下面地址可以自己網(wǎng)上搜。
下面是我測試一個效果視頻【僅供學(xué)習(xí)】:?
虛擬攝像頭插件,玩玩,支持微信QQ,替換攝像頭,還是開源的?。?!
下面是實(shí)現(xiàn)HOOk的java代碼,我已經(jīng)用Smali導(dǎo)出來了:
===================================================================
//
// 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;
????}
}文章來源:http://www.zghlxwxcb.cn/news/detail-795757.html
=================================================================?文章來源地址http://www.zghlxwxcb.cn/news/detail-795757.html
到了這里,關(guān)于安卓虛擬相機(jī)虛擬攝像頭插件,IOS蘋果iphone,微信QQ都支持,提供dex\hook類代碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!