|
@@ -1,7 +1,8 @@
|
|
|
import asyncio
|
|
|
+import io
|
|
|
from concurrent.futures import ProcessPoolExecutor
|
|
|
from itertools import groupby
|
|
|
-
|
|
|
+import numpy as np
|
|
|
import bitstring
|
|
|
from linuxpy.video.device import Device
|
|
|
from Crypto.Hash import BLAKE2b
|
|
@@ -11,9 +12,25 @@ from loguru import logger
|
|
|
logger.level("INFO")
|
|
|
|
|
|
|
|
|
-def chunks(lst, n):
|
|
|
- for i in range(0, len(lst), n):
|
|
|
- yield lst[i: i + n]
|
|
|
+def split_array_numpy(data):
|
|
|
+ data_np = np.frombuffer(data, dtype=np.uint32)
|
|
|
+ first = data_np[::2].tobytes()
|
|
|
+ second = data_np[1::2].tobytes()
|
|
|
+ return first, second
|
|
|
+
|
|
|
+
|
|
|
+def xor_arrays_numpy(arr1, arr2):
|
|
|
+ a = np.frombuffer(arr1, dtype=np.uint32)
|
|
|
+ b = np.frombuffer(arr2, dtype=np.uint32)
|
|
|
+ return np.bitwise_xor(a, b).tobytes()
|
|
|
+
|
|
|
+
|
|
|
+def chunks(in_bytes: bytes, take_n: int) -> bytes:
|
|
|
+ bytes_buffer = io.BytesIO(in_bytes)
|
|
|
+ bytes_send = bytes_buffer.read(take_n)
|
|
|
+ while len(bytes_send) == take_n:
|
|
|
+ yield bytes_send
|
|
|
+ bytes_send = bytes_buffer.read(take_n)
|
|
|
|
|
|
|
|
|
def extract_lsbs(data):
|
|
@@ -22,6 +39,7 @@ def extract_lsbs(data):
|
|
|
buffer = []
|
|
|
|
|
|
data = [k for k, _ in groupby(data)]
|
|
|
+ data = bytes(data)
|
|
|
data = chunks(data, 8)
|
|
|
|
|
|
for chunk in data:
|
|
@@ -52,14 +70,16 @@ def whiten(data: bytes) -> bytes:
|
|
|
|
|
|
def video2_extractor(frame_bytes: bytes):
|
|
|
logger.debug(f"frames_in {len(frame_bytes)}")
|
|
|
- chunked_bytes = chunks(frame_bytes, 8)
|
|
|
- newdata = b""
|
|
|
+ # chunked_bytes = chunks(frame_bytes, 8)
|
|
|
+ # newdata = b""
|
|
|
|
|
|
- for chunk in chunked_bytes:
|
|
|
- newdata += bytes(a ^ b for a, b in zip(chunk[:4], chunk[4:]))
|
|
|
+ first_part, second_part = split_array_numpy(frame_bytes)
|
|
|
+ new_data = xor_arrays_numpy(first_part, second_part)
|
|
|
+ # for chunk in chunked_bytes:
|
|
|
+ # newdata += bytes(a ^ b for a, b in zip(chunk[:4], chunk[4:]))
|
|
|
|
|
|
- logger.debug(f"newdata {len(newdata)}")
|
|
|
- out_bytes = extract_lsbs(newdata)
|
|
|
+ logger.debug(f"new data {len(new_data)}")
|
|
|
+ out_bytes = extract_lsbs(new_data)
|
|
|
out_bytes = whiten(out_bytes)
|
|
|
|
|
|
logger.info(f"Sample ready: {len(out_bytes)}b.")
|
|
@@ -87,7 +107,8 @@ class FrameTakeWorker:
|
|
|
return next(self.frame_gen)
|
|
|
|
|
|
def __del__(self):
|
|
|
- self.frame_gen.close()
|
|
|
+ if self.frame_gen:
|
|
|
+ self.frame_gen.close()
|
|
|
|
|
|
async def frame_extractor(self, frame_bytes: bytes):
|
|
|
loop = asyncio.get_event_loop()
|