当前位置:网站首页>Tempest HDMI leak receive 2
Tempest HDMI leak receive 2
2022-06-25 07:24:00 【Lao Shao's open source world】
I found it later gr-tempest package , It's based on gnuradio Reset tempestsdr, Because it is gnuradio, It is convenient for me to install locally , So I ran , It didn't work out , Maybe because it defaults to usrp, I'm using hackrf+ Resampling , The hardware is different . But there's another one in it simulate The flow chart of , You can import the picture and re solve it . I succeeded in this game , By debugging , I found that in different sample correction when , There will be something like the first article , There will also be decent pictures . So my confidence greatly increased .
Later, I decided to be in my former c++/hackrf Implementation of the analog video demodulation program to try . Sure enough, it worked , The main secret is to get rid of all kinds of synchronization in analog video demodulation , Remove interlacing , Then patiently adjust the row width , Finally, in order to get better results , Don't jump , It is recommended to artificially limit the refresh interval .
Here is my code :
#include <iostream>
#include <signal.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <libhackrf/hackrf.h>
#include <pthread.h>
#include <unistd.h>
#include <string>
#include <sstream>
using namespace std;
using namespace cv;
int decimate_rate = 1;
//#define original_width_x_height 65100
static volatile bool do_exit = false;
int result;
static hackrf_device* device = NULL;
double sample_rate_hz = 6e6/decimate_rate * 1.951047 ;
double baseband_filter_bw_hz = 1e6 ;
double freq_hz = 395.991*1000000;
Mat frame;
int x = 0;
int y = 0;
int correctX = 0;
int correctY = 0;
int autoCorrectX = 0;
int autoCorrectY = 0;
int width = 2081; //multiple of 347 like 2081 or 1387
int height = 800;
int original_width = width / decimate_rate;
int original_width_x_height = original_width * height;
int inverseVideo = 1;
double maxSignalLevel = 0;
double blackLevel = 0;
double coeff = 0;
double agcSignalLevel = 0;
int pixelCounter = 0;
double contrast = 40;
double bright = 40;
int delay_count = 0;
bool bufferIsFull = false;
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
//double grayScaleValues[original_width_x_height];
double grayScaleValues[2000000];
void sigint_callback_handler(int signum)
{
cout << "Caught signal" << endl;
do_exit = true;
}
void draw_pixel(double mag)
{
if (x >= original_width)
{
y += 1;
x = 0;
}
if (y >= height)
{
y = 0;
delay_count++;
if (delay_count > 3)
{
bufferIsFull = true;
delay_count = 0;
}
}
double num2 = (blackLevel - mag) * coeff * contrast;
num2 += bright;
if (num2 > 255)
{
num2 = 255;
}
if (num2 < 0)
{
num2 = 0;
}
int num = y % height * original_width + x % original_width;
grayScaleValues[num] = num2;
x = x + 1;
}
int rx_callback(hackrf_transfer* transfer)
{
double im, re, mag;
double num = 0;
double num2 = 0;
double compare_re;
for( uint32_t i = 0; i < transfer->valid_length; i += 2)
{
// int8_t(transfer->buffer[i]) -128~127
im = (int8_t(transfer->buffer[i]))/128.0;
re = (int8_t(transfer->buffer[i + 1]))/128.0;
compare_re = abs(int8_t(transfer->buffer[i+1])) ;
if (compare_re > num)
{
num = compare_re;
}
double mag = sqrt( im * im + re * re); //mag 0~1.414
if (mag > num2)
{
num2 = mag;
}
if (inverseVideo)
{
mag = maxSignalLevel - mag;
}
pthread_mutex_lock(&mtx);
draw_pixel(mag);
pthread_mutex_unlock(&mtx);
//grey of opencv is 0~255
//0 is black 255 is white
}
maxSignalLevel = maxSignalLevel * 0.9 + num2 * 0.1;
blackLevel = maxSignalLevel * 0.4;
coeff = 255 / blackLevel;
agcSignalLevel = num;
return 0;
}
void *receiving_function(void *arg)
{
while (do_exit == false)
{
sleep(1);
}
cout << "Thread Exiting..." << endl;
pthread_exit(NULL);
}
int main()
{
pthread_t recv_th;
signal(SIGINT, &sigint_callback_handler);
frame = Mat::zeros(height, width, CV_8UC1);
result = hackrf_init();
if( result != HACKRF_SUCCESS )
{
cout << "hackrf_init() failed" << endl;
return EXIT_FAILURE;
}
result = hackrf_open(&device);
if( result != HACKRF_SUCCESS )
{
cout << "hackrf_open() failed" << endl;
return EXIT_FAILURE;
}
result = hackrf_set_sample_rate(device, sample_rate_hz);
if( result != HACKRF_SUCCESS )
{
cout << "hackrf_set_sample_rate() failed" << endl;
return EXIT_FAILURE;
}
result = hackrf_set_baseband_filter_bandwidth(device, baseband_filter_bw_hz);
if( result != HACKRF_SUCCESS )
{
cout << "hackrf_baseband_filter_bandwidth_set() failed" << endl;
return EXIT_FAILURE;
}
result = hackrf_set_freq(device, freq_hz);
if( result != HACKRF_SUCCESS )
{
cout << "hackrf_set_freq() failed" << endl;
return EXIT_FAILURE;
}
result = hackrf_set_lna_gain(device, 40);
if( result != HACKRF_SUCCESS )
{
cout << "hackrf_set_lna_gain() failed" << endl;
return EXIT_FAILURE;
}
result = hackrf_set_vga_gain(device, 26);
if( result != HACKRF_SUCCESS )
{
cout << "hackrf_set_vga_gain() failed" << endl;
return EXIT_FAILURE;
}
int err = pthread_create(&recv_th, NULL, receiving_function, NULL);
if (err != 0)
{
cout << "Create thread failed" << endl;
}
result = hackrf_start_rx(device, rx_callback, NULL);
while( (hackrf_is_streaming(device) == HACKRF_TRUE) && (do_exit == false) )
{
if (bufferIsFull)
{
pthread_mutex_lock(&mtx);
for (int counter = 0; counter < original_width_x_height; counter++)
{
int new_x = counter % original_width;
int new_y = counter / original_width;
for (int c = 0; c < decimate_rate; c++)
{
frame.at<uchar>(new_y, new_x*decimate_rate + c) = grayScaleValues[counter];
}
grayScaleValues[counter] = 0;
}
bufferIsFull = false;
pthread_mutex_unlock(&mtx);
}
imshow("frame", frame);
if (waitKey(5) == 'q')
{
do_exit = true;
break;
}
}
if (do_exit)
{
cout << "Exiting..." << endl;
}
result = hackrf_close(device);
if(result != HACKRF_SUCCESS)
{
cout << "hackrf_close() failed" << endl;
}
else
{
cout << "hackrf_close() done" << endl;
}
hackrf_exit();
cout << "hackrf_exit() done" << endl;
pthread_join(recv_th,NULL);
return 0;
}
The following is the command for compiling :
g++ hackrf_tv_hdmi.cpp -o hackrf_tv_hdmi `pkg-config --cflags --libs opencv` -lhackrf -pthreadInterested friends can try , My monitor is set to 1920x1080 60Hz. Your frequency is different from mine .
Now this c++ The version code must be tempestsdr It's much simpler , But it is still not the simplest , There are many redundant codes when I do analog video demodulation . When I have time, I'll sort it out as python edition .
边栏推荐
- 【一起上水硕系列】Day 5
- 高考志愿填报,为啥专业最后考虑?
- Event registration | Apache pulsar x kubesphere online meetup is coming
- Debug through yalc before releasing NPM package
- Rotation vector (rotation matrix) and Euler angle
- Orcad Schematic常用功能
- Authentique Photoshop 2022 expérience d'achat partage
- 【UVM入門 ===> Episode_9 】~ 寄存器模型、寄存器模型的集成、寄存器模型的常規方法、寄存器模型的應用場景
- 13 `bs_duixiang.tag标签`得到一个tag对象
- Escape analysis of 982 golang
猜你喜欢

我们不一样

From perceptron to transformer, a brief history of deep learning

The significance and proof of weak large number theorem

【一起上水硕系列】Day 5

Make enough money to go back home

正版photoshop2022购买体验经历分享

稳压二极管的原理,它有什么作用?

为什么要“除夕”,原来是内存爆了!

48 张图 | 手摸手教你微服务的性能监控、压测和调优
![[introduction to UVM== > episode_9] ~ register model, integration of register model, general methods of register model, application scenarios of register model](/img/c0/b373a3f0e0c7b35f42c8a28b4d4f74.png)
[introduction to UVM== > episode_9] ~ register model, integration of register model, general methods of register model, application scenarios of register model
随机推荐
Why "New Year's Eve", the original memory burst!
活动报名|Apache Pulsar x KubeSphere 在线 Meetup 火热报名中
Redirect to previous page after login? PHP - Redirecting to previous page after login? PHP
【UVM入门 ===> Episode_9 】~ 寄存器模型、寄存器模型的集成、寄存器模型的常规方法、寄存器模型的应用场景
深入解析 Apache BookKeeper 系列:第三篇——读取原理
3632. Binary sum
Escape analysis of 982 golang
Cocos学习日记3——api获取节点、组件
13 `bs_duixiang.tag标签`得到一个tag对象
Several good weather plug-ins
太美的承诺因为太年轻
Display purchase Summary - Dell 2705qm BenQ pd2700u
[C language] add separator to string
Lotus v1.16.0-rc2 Calibration net
Solar orbiter captured the full picture of the largest prominence eruption in history
How to store the directory / hierarchy / tree structure in the database- How to store directory / hierarchy / tree structure in the database?
TEMPEST HDMI泄漏接收 2
【LeetCode】two num·两数之和
[introduction to UVM== > episode_9] ~ register model, integration of register model, general methods of register model, application scenarios of register model
Conditional grouping with $exists inside $cond