讀取YUV數據到AVFrame并用多線程控制幀率

?文件樹:

?1.xvideo_view.h

class XVideoView
{
public:// 像素格式枚舉enum Format { RGBA = 0, ARGB, YUV420P };// 渲染類型枚舉enum RenderType { SDL = 0 };// 創建渲染對象的靜態方法static XVideoView* Create(RenderType type = SDL);// 繪制幀的方法bool DrawFrame(AVFrame* frame);// 純虛函數,需在派生類中實現virtual bool Init(int w, int h, Format fmt = RGBA, void* win_id = nullptr) = 0;virtual void Close() = 0;virtual bool IsExit() = 0;virtual bool Draw(const unsigned char* data, int linesize = 0) = 0;virtual bool Draw(const unsigned char* y, int y_pitch, const unsigned char* u, int u_pitch, const unsigned char* v, int v_pitch) = 0;// 調整顯示大小的方法void Scale(int w, int h);// 獲取顯示幀率的方法int render_fps();protected:// 成員變量int render_fps_ = 0;       // 顯示幀率int width_ = 0;            // 材質寬度int height_ = 0;           // 材質高度Format fmt_ = RGBA;        // 像素格式std::mutex mtx_;           // 互斥鎖,確保線程安全int scale_w_ = 0;          // 顯示寬度int scale_h_ = 0;          // 顯示高度long long beg_ms_ = 0;     // 計時開始時間int count_ = 0;            // 統計顯示次數
};

2. xsdl.h

#pragma once#include "xvideo_view.h"// 前向聲明 SDL 結構體
struct SDL_Window;
struct SDL_Renderer;
struct SDL_Texture;// 定義繼承自 XVideoView 的 XSDL 類
class XSDL : public XVideoView
{
public:// 關閉渲染窗口,覆蓋基類的純虛函數void Close() override;/// 初始化渲染窗口,線程安全/// @param w 窗口寬度/// @param h 窗口高度/// @param fmt 繪制的像素格式/// @param win_id 窗口句柄,如果為空,創建新窗口/// @return 是否創建成功bool Init(int w, int h,Format fmt = RGBA,void* win_id = nullptr) override;///// 渲染圖像,線程安全/// @param data 渲染的二進制數據/// @param linesize 一行數據的字節數,對于 YUV420P 就是 Y 一行字節數/// @param linesize <= 0 就根據寬度和像素格式自動算出大小/// @return 渲染是否成功bool Draw(const unsigned char* data,int linesize = 0) override;// 渲染 YUV420P 圖像,線程安全bool Draw(const unsigned char* y, int y_pitch,const unsigned char* u, int u_pitch,const unsigned char* v, int v_pitch) override;// 判斷是否退出,覆蓋基類的純虛函數bool IsExit() override;private:// SDL 相關成員變量,用于管理窗口、渲染器和紋理SDL_Window* win_ = nullptr;SDL_Renderer* render_ = nullptr;SDL_Texture* texture_ = nullptr;
};

3.sdlqtrgb.h

#pragma once#include <QtWidgets/QWidget>
#include "ui_sdlqtrgb.h"
#include <thread>// 定義繼承自 QWidget 的 SdlQtRGB 類
class SdlQtRGB : public QWidget
{Q_OBJECTpublic:// 構造函數SdlQtRGB(QWidget* parent = Q_NULLPTR);// 析構函數~SdlQtRGB(){is_exit_ = true;// 等待渲染線程退出th_.join();// 當前線程(主線程)將等待,直到 th 線程完成}// 定時器事件處理void timerEvent(QTimerEvent* ev) override;// 窗口大小調整事件處理void resizeEvent(QResizeEvent* ev) override;// 線程函數,用于刷新視頻void Main();signals:// 信號函數,將任務放入列表void ViewS();public slots:// 顯示的槽函數void View();private:std::thread th_;           // 渲染線程bool is_exit_ = false;     // 處理線程退出Ui::SdlQtRGBClass ui;      // UI 組件
};

4.xvideo_view.cpp


#include "xsdl.h"
#include <thread>
using namespace std;
extern "C"
{
#include <libavcodec/avcodec.h>
}
#pragma comment(lib,"avutil.lib")void MSleep(unsigned int ms)
{auto beg = clock();for (int i = 0; i < ms; i++){this_thread::sleep_for(1ms);if ((clock() - beg) / (CLOCKS_PER_SEC / 1000) >= ms)break;}
}
//MSleep 函數實現了一個基于忙等待和定時器的睡眠功能。它將當前線程暫停執行一段時間(以毫秒為單位)XVideoView* XVideoView::Create(RenderType type)
{switch (type){case XVideoView::SDL:return new XSDL();break;default:break;}return nullptr;
}
bool XVideoView::DrawFrame(AVFrame* frame)
{if (!frame || !frame->data[0])return false;count_++;if (beg_ms_ <= 0){beg_ms_ = clock();}//計算顯示幀率else if ((clock() - beg_ms_) / (CLOCKS_PER_SEC / 1000) >= 1000) //一秒計算一次fps{render_fps_ = count_;count_ = 0;beg_ms_ = clock();}//假如一秒鐘調用了20次DrawFrame,count=20,表示一秒鐘渲染了20次圖像,即FPS=20,count置于零switch (frame->format){case AV_PIX_FMT_YUV420P:return Draw(frame->data[0], frame->linesize[0],//Yframe->data[1], frame->linesize[1],	//Uframe->data[2], frame->linesize[2]	//V);case AV_PIX_FMT_BGRA:return Draw(frame->data[0], frame->linesize[0]);default:break;}return false;
}
  • else if ((clock() - beg_ms_) / (CLOCKS_PER_SEC / 1000) >= 1000)
    • clock() - beg_ms_:計算從 beg_ms_ 到當前時間經過的時鐘周期數。
    • CLOCKS_PER_SEC:宏定義,表示每秒的時鐘周期數。通常值是 1000000 或 1000,取決于系統。
    • (clock() - beg_ms_) / (CLOCKS_PER_SEC / 1000):將經過的時鐘周期數轉換為毫秒,再檢查是否已經過了 1000 毫秒(即 1 秒)。
  • render_fps_ = count_;:將當前幀計數 count_ 賦值給 render_fps_,表示過去一秒內顯示的幀數,即 FPS。
  • count_ = 0;:重置幀計數器,為下一秒重新計數。
  • beg_ms_ = clock();:重置開始時間,記錄當前時間,開始新的計時周期。

?5.xsdl.cpp


#include "xsdl.h"
#include <sdl/SDL.h>
#include <iostream>
using namespace std;
#pragma comment(lib,"SDL2.lib")
static bool InitVideo()
{static bool is_first = true;static mutex mux;unique_lock<mutex> sdl_lock(mux);if (!is_first)return true;is_first = false;if (SDL_Init(SDL_INIT_VIDEO)){cout << SDL_GetError() << endl;return false;}//設定縮放算法,解決鋸齒問題,線性插值算法SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");return true;
}
bool XSDL::IsExit()
{SDL_Event ev;SDL_WaitEventTimeout(&ev, 1);if (ev.type == SDL_QUIT)return true;return false;
}
該函數通過調用 SDL 庫提供的函數等待事件,如果接收到退出事件,則返回 true,否則返回 false。這種方法用于輪詢事件隊列,以便及時響應用戶的退出操作。void XSDL::Close()
{//確保線程安全unique_lock<mutex> sdl_lock(mtx_);if (texture_){SDL_DestroyTexture(texture_);texture_ = nullptr;}if (render_){SDL_DestroyRenderer(render_);render_ = nullptr;}if (win_){SDL_DestroyWindow(win_);win_ = nullptr;}
}
該 Close 函數用于關閉 SDL 窗口和相關資源。在關閉窗口之前,它使用互斥量確保線程安全性。然后,依次銷毀 SDL 窗口、渲染器和紋理對象,并將相應的指針置為空,以防止內存泄漏和懸空指針。通過這樣的實現,可以安全地關閉 SDL 窗口和釋放相關資源,確保程序運行的穩定性和正確性。bool XSDL::Init(int w, int h, Format fmt, void* win_id)
{if (w <= 0 || h <= 0)return false;//初始化SDL 視頻庫InitVideo();//確保線程安全unique_lock<mutex> sdl_lock(mtx_);width_ = w;height_ = h;fmt_ = fmt;if (texture_)SDL_DestroyTexture(texture_);if (render_)SDL_DestroyRenderer(render_);///1 創建窗口if (!win_){if (!win_id){//新建窗口win_ = SDL_CreateWindow("",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,w, h, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);}else{//渲染到控件窗口win_ = SDL_CreateWindowFrom(win_id);}}if (!win_){cerr << SDL_GetError() << endl;return false;}/// 2 創建渲染器render_ = SDL_CreateRenderer(win_, -1, SDL_RENDERER_ACCELERATED);if (!render_){cerr << SDL_GetError() << endl;return false;}//創建材質 (顯存)unsigned int sdl_fmt = SDL_PIXELFORMAT_RGBA8888;switch (fmt){case XVideoView::RGBA:break;case XVideoView::ARGB:sdl_fmt = SDL_PIXELFORMAT_ARGB32;break;case XVideoView::YUV420P:sdl_fmt = SDL_PIXELFORMAT_IYUV;break;default:break;}texture_ = SDL_CreateTexture(render_,sdl_fmt,                        //像素格式SDL_TEXTUREACCESS_STREAMING,    //頻繁修改的渲染(帶鎖)w, h                            //材質大小);if (!texture_){cerr << SDL_GetError() << endl;return false;}return true;
}
bool XSDL::Draw(const unsigned  char* y, int y_pitch,const unsigned  char* u, int u_pitch,const unsigned  char* v, int v_pitch
)
{//參數檢查if (!y || !u || !v)return false;unique_lock<mutex> sdl_lock(mtx_);if (!texture_ || !render_ || !win_ || width_ <= 0 || height_ <= 0)return false;//復制內存到顯顯存auto re = SDL_UpdateYUVTexture(texture_,NULL,y, y_pitch,u, u_pitch,v, v_pitch);if (re != 0){cout << SDL_GetError() << endl;return false;}//清空屏幕SDL_RenderClear(render_);//材質復制到渲染器SDL_Rect rect;SDL_Rect* prect = nullptr;if (scale_w_ > 0)  //用戶手動設置縮放{rect.x = 0; rect.y = 0;rect.w = scale_w_;//渲染的寬高,可縮放rect.h = scale_w_;prect = &rect;}re = SDL_RenderCopy(render_, texture_, NULL, prect);if (re != 0){cout << SDL_GetError() << endl;return false;}SDL_RenderPresent(render_);
}
bool XSDL::Draw(const unsigned char* data, int linesize)
{if (!data)return false;unique_lock<mutex> sdl_lock(mtx_);if (!texture_ || !render_ || !win_ || width_ <= 0 || height_ <= 0)return false;if (linesize <= 0){switch (fmt_){case XVideoView::RGBA:case XVideoView::ARGB:linesize = width_ * 4;break;case XVideoView::YUV420P:linesize = width_;break;default:break;}}if (linesize <= 0)return false;//復制內存到顯顯存auto re = SDL_UpdateTexture(texture_, NULL, data, linesize);if (re != 0){cout << SDL_GetError() << endl;return false;}//清空屏幕SDL_RenderClear(render_);//材質復制到渲染器SDL_Rect rect;SDL_Rect* prect = nullptr;if (scale_w_ > 0)  //用戶手動設置縮放{rect.x = 0; rect.y = 0;rect.w = scale_w_;//渲染的寬高,可縮放rect.h = scale_w_;prect = &rect;}re = SDL_RenderCopy(render_, texture_, NULL, prect);if (re != 0){cout << SDL_GetError() << endl;return false;}SDL_RenderPresent(render_);return true;
}

draw函數解析:

  • 首先進行了參數檢查。檢查輸入的 YUV 數據指針是否為非空,如果有任何一個為空,則返回 false
  • 接著使用獨占鎖 sdl_lock 對 SDL 窗口相關資源進行保護,確保在繪制過程中不會被其他線程干擾。
  • 進一步檢查 SDL 相關資源是否已經初始化,并且窗口的寬度和高度是否大于零,如果存在任何不滿足條件的情況,則返回 false
  • 使用 SDL_UpdateYUVTexture 函數將 YUV 數據復制到顯存中的紋理對象中。這個函數會更新已經存在的 YUV 紋理,以便后續渲染到屏幕上。
  • 使用 SDL_RenderClear 函數清空渲染器的渲染目標,即清空屏幕。
  • 根據用戶是否手動設置縮放參數,設置渲染區域的大小。
  • 使用 SDL_RenderCopy 函數將紋理對象復制到渲染器中,并在屏幕上渲染出來。
  • 最后,使用 SDL_RenderPresent 函數將渲染器中的內容呈現到屏幕上,完成一幀的繪制。
  • Draw 函數用于在 SDL 窗口中繪制 YUV 格式的圖像。它首先將 YUV 數據復制到紋理對象中,然后清空屏幕并將紋理對象渲染到屏幕上。通過這種方式,可以實現基于 SDL 的視頻播放功能。

對比兩個draw函數

第二個draw函數處理 YUV 數據的方式相對來說更簡單,因為它只需要處理單個分量的數據(一個數組),而不需要分別處理 Y、U、V 三個分量(三個數組)。這種處理方式可能在一些情況下效率更高,特別是當只需要顯示圖像的亮度信息時,而對色度信息的準確性要求不是很高時,使用單個分量的方法會更加簡潔和高效。

第一個draw函數處理 YUV 數據的優點主要體現在以下幾個方面:

  1. 精確控制每個分量:第一個函數能夠分別處理 Y、U、V 三個分量的數據,可以對每個分量進行精確的控制和處理,適用于需要對圖像的亮度和色度信息進行精細調節的場景。

  2. 靈活性:通過分別處理每個分量,可以實現更多樣化的圖像處理操作,如亮度調整、對比度調整、色調轉換等。這種靈活性使得第一個函數在一些特定的應用場景中更加適用。

  3. 兼容性:在某些情況下,需要對 YUV 數據進行特定格式的處理,比如將 YUV 數據轉換為其他格式或者進行編解碼操作。通過分別處理 Y、U、V 三個分量,可以更容易地滿足這些需求,提高代碼的兼容性和通用性。

總的來說,第一個函數適用于對圖像進行復雜處理和轉換的場景,能夠提供更多的靈活性和控制能力。而第二個函數則更適用于簡單的圖像顯示場景,能夠提供更高的處理效率和性能。選擇哪個函數取決于具體的需求和應用場景。

6.sdlqtrgb.cpp


#include "sdlqtrgb.h"
#include <fstream>
#include <iostream>
#include <QMessageBox>
#include <thread>
#include <sstream>
#include <QSpinBox>
#include "xvideo_view.h"
extern "C"
{
#include <libavcodec/avcodec.h>
}using namespace std;static int sdl_width = 0;
static int sdl_height = 0;
static int pix_size = 2;
static ifstream yuv_file;
static XVideoView* view = nullptr;
static AVFrame* frame = nullptr;
static long long file_size = 0;
static QLabel* view_fps = nullptr; //顯示fps控件
static QSpinBox* set_fps = nullptr;//設置fps控件
int fps = 25; //播放幀率
void SdlQtRGB::timerEvent(QTimerEvent* ev)
{//yuv_file.read((char*)yuv, sdl_width * sdl_height * 1.5);// yuv420p// 4*2// yyyy yyyy // u    u// v    vyuv_file.read((char*)frame->data[0], sdl_width * sdl_height);//Yyuv_file.read((char*)frame->data[1], sdl_width * sdl_height / 4);//Uyuv_file.read((char*)frame->data[2], sdl_width * sdl_height / 4);//Vif (view->IsExit()){view->Close();exit(0);}view->DrawFrame(frame);//view->Draw(yuv);
}void SdlQtRGB::View()
{yuv_file.read((char*)frame->data[0], sdl_width * sdl_height);//Yyuv_file.read((char*)frame->data[1], sdl_width * sdl_height / 4);//Uyuv_file.read((char*)frame->data[2], sdl_width * sdl_height / 4);//Vif (yuv_file.tellg() == file_size) //讀取到文件結尾{yuv_file.seekg(0, ios::beg);}//yuv_file.gcount()//yuv_file.seekg() 結尾處seekg無效if (view->IsExit()){view->Close();exit(0);}view->DrawFrame(frame);stringstream ss;ss << "fps:" << view->render_fps();//只能在槽函數中調用view_fps->setText(ss.str().c_str());fps = set_fps->value(); //拿到播放幀率
}void SdlQtRGB::Main()
{while (!is_exit_){ViewS();if (fps > 0){MSleep(1000 / fps);}elseMSleep(10);}
}
SdlQtRGB::SdlQtRGB(QWidget* parent): QWidget(parent)
{//打開yuv文件yuv_file.open("400_300_25.yuv", ios::binary);if (!yuv_file){QMessageBox::information(this, "", "open yuv failed!");return;}yuv_file.seekg(0, ios::end);   //移到文件結尾file_size = yuv_file.tellg();   //文件指針位置yuv_file.seekg(0, ios::beg);ui.setupUi(this);//綁定渲染信號槽connect(this, SIGNAL(ViewS()), this, SLOT(View()));//顯示fps的控件view_fps = new QLabel(this);view_fps->setText("fps:100");//設置fpsset_fps = new QSpinBox(this);set_fps->move(200, 0);set_fps->setValue(25);set_fps->setRange(1, 300);sdl_width = 400;sdl_height = 300;ui.label->resize(sdl_width, sdl_height);view = XVideoView::Create();//view->Init(sdl_width, sdl_height,//    XVideoView::YUV420P);//view->Close();view->Close();view->Init(sdl_width, sdl_height,XVideoView::YUV420P, (void*)ui.label->winId());//生成frame對象空間frame = av_frame_alloc();frame->width = sdl_width;frame->height = sdl_height;frame->format = AV_PIX_FMT_YUV420P;//  Y Y//   UV//  Y Yframe->linesize[0] = sdl_width;     //Yframe->linesize[1] = sdl_width / 2;   //Uframe->linesize[2] = sdl_width / 2;   //V//生成圖像空間 默認32字節對齊auto re = av_frame_get_buffer(frame, 0);if (re != 0){char buf[1024] = { 0 };av_strerror(re, buf, sizeof(buf));cerr << buf << endl;}//startTimer(10);th_ = std::thread(&SdlQtRGB::Main, this);
}void SdlQtRGB::resizeEvent(QResizeEvent* ev)
{ui.label->resize(size());ui.label->move(0, 0);//view->Scale(width(), height());
}

timeEvent函數解析:

  • ? 從文件中依次讀取 YUV420P 格式的視頻幀數據,分別存儲到 frame->data[0](Y 分量)、frame->data[1](U 分量)和 frame->data[2](V 分量)中。根據 YUV420P 格式的特點,U 和 V 分量的大小是 Y 分量的四分之一。
  • 調用 XVideoView 類的 DrawFrame 函數來渲染讀取到的視頻幀數據。這個函數會將 YUV 數據傳遞給渲染器進行顯示。

view函數解析:

  • ? 如果讀取到文件結尾,就將文件指針移到文件開頭,實現視頻循環播放。
  • view->DrawFrame(frame);: 這行代碼調用了 XVideoView 類的 DrawFrame 函數,將從視頻文件中讀取的幀數據 frame 渲染到屏幕上。具體的渲染邏輯在 DrawFrame 函數中實現。

  • stringstream ss;: 創建了一個 stringstream 對象 ss,用于構建幀率信息的字符串。

  • ss << "fps:" << view->render_fps();: 將幀率信息拼接到 ss 中。view->render_fps() 會調用 XVideoView 對象的 render_fps() 方法來獲取當前的渲染幀率,然后將其拼接到字符串后面。

  • view_fps->setText(ss.str().c_str());: 將構建好的幀率信息字符串設置到界面上用于顯示幀率的文本框 view_fps 中。ss.str()stringstream 對象轉換為 std::string 類型,然后通過 setText 函數將其設置到界面上。

  • fps = set_fps->value();: 獲取用戶設置的播放幀率。這里假設 set_fps 是一個用戶用于設置播放幀率的控件(如滑塊、輸入框等),通過 value 屬性獲取用戶設置的播放幀率,并將其保存在變量 fps 中。

Main函數解析:

SdlQtRGB::Main 方法是一個視頻播放的主循環,不斷地顯示視頻幀,控制播放幀率,直到退出條件滿足為止。

sdlQtRGB構造函數解析:

  • std::thread(&SdlQtRGB::Main, this) 表示創建了一個新的線程,線程的入口函數是 SdlQtRGB 類的 Main 方法,當前對象的指針作為參數傳遞給線程。
  • yuv_file.seekg(0, ios::end);: 將文件指針移動到文件的末尾。通過將文件指針移動到文件末尾,然后調用 tellg() 函數獲取文件指針的位置,就可以得到文件的大小。

  • file_size = yuv_file.tellg();: 獲取文件指針的位置,即文件的大小,并將其賦值給變量 file_size。這樣,file_size 變量就存儲了 YUV 文件的大小。

  • yuv_file.seekg(0, ios::beg);: 將文件指針重新移動到文件的開頭。這是為了在后續操作中重新使用文件時將文件指針定位到文件的起始位置。

7.運行過程:

  • 程序初始化:

    • 包括全局變量的初始化、配置文件的加載等操作。
  • 創建 SdlQtRGB 對象:

    • 在主函數中,會創建一個 SdlQtRGB 對象,這將觸發 SdlQtRGB 類的構造函數執行。
  • 初始化界面和文件:

    • SdlQtRGB 類的構造函數中,會初始化界面、打開 YUV 文件,并獲取文件大小等操作。
  • 創建視頻渲染器和幀對象:

    • 在構造函數中會創建視頻渲染器對象 view,并初始化它。
    • 創建 AVFrame 對象 frame,分配內存空間并設置幀的寬度、高度和像素格式為 YUV420P。
  • 啟動視頻播放主循環線程:

    • 在構造函數中,通過創建線程的方式啟動視頻播放主循環,即調用 SdlQtRGB::Main 方法。
  • 主循環運行:

    • SdlQtRGB::Main 方法中,程序會進入主循環,不斷地執行視頻播放的相關操作。
    • 主循環中會不斷地讀取 YUV 文件中的數據,并將數據傳遞給渲染器進行渲染。
  • 渲染幀和更新界面:

    • View 方法中,會不斷地讀取 YUV 數據,然后將其傳遞給渲染器進行渲染。
    • 同時,程序會更新界面上顯示的幀率信息。
  • 用戶交互和定時操作:

    • 程序會監聽用戶輸入,響應鍵盤、鼠標等事件。
    • 如果設置了播放幀率,程序會根據幀率控制視頻播放的速度。
  • 退出和清理:

    • 當用戶關閉程序或觸發退出條件時,程序會退出主循環。
    • 程序會執行必要的清理操作,包括釋放資源、關閉文件等。

8.特別注意對幀率的調整過程:

在view函數中,最后兩行,

view_fps->setText(ss.str().c_str());
//左上角顯示幀率
fps = set_fps->value(); 

?? 通過調整?QSpinBox控件來拿到要播放幀率,若調整到40,則fps=40,在Main函數中通過fps參數將視頻渲染的fps調整到40幀率
比如 fps = 40,MSleep(1000/40)即MSleep(25),即休眠25ms,即兩幅圖像渲染的時間間隔為25ms,1000ms 共有40個25ms,即40副圖像,一秒渲染40副圖像 ,即fps = 40?

?

9.運行結果:

這里我們可以通過QspinBox控件來調整視頻播放的幀率,幀率越高播放速度越快。

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/19687.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/19687.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/19687.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

影響生產RAG流水線5大瓶頸

檢索增強生成&#xff08;Retrieval Augmented Generation&#xff0c;RAG&#xff09;已成為基于大型語言模型的生成式人工智能應用的關鍵組成部分。其主要目標是通過將通用語言模型與外部信息檢索系統集成&#xff0c;增強通用語言模型的能力。這種混合方法旨在解決傳統語言模…

無法刪除dll文件

碰到xxxxxx.dll文件無法刪除不要慌&#xff01; 通過Tasklist /m dll文件名稱 去查看它和哪個系統文件綁定運行&#xff0c;發現是explorer.exe。 我們如果直接通過del命令【當然需要在該dll文件所在的路徑中】。發現拒絕訪問 我們需要在任務管理器中&#xff0c;將資源管理器…

如何處理網安發出的網絡安全監督檢查限期整改通知

近期&#xff0c;很多客戶都收到了網安發出的限期整改通知。大家都比較關心的問題是&#xff0c;如何應對處理這些限期整改通知。后續是否有其他的影響&#xff0c;需要如何做進一步的優化整改和調整。今天就這些問題給大家做一些分享。 一. 為什么會有網安的網絡安全檢查 主…

大多數JAVA程序員都干不到35歲嗎?

在開始前剛好我有一些資料&#xff0c;是我根據網友給的問題精心整理了一份「 Java的資料從專業入門到高級教程」&#xff0c; 點個關注在評論區回復“888”之后私信回復“888”&#xff0c;全部無償共享給大家&#xff01;&#xff01;&#xff01;不少人認為的程序員吃青春飯…

邊緣計算:推動智能時代的前沿技術

邊緣計算:推動智能時代的前沿技術 引言 隨著物聯網(IoT)、5G通信和人工智能(AI)技術的迅猛發展,邊緣計算(Edge Computing)成為現代計算架構中的一個重要組成部分。邊緣計算通過將數據處理和存儲移至網絡邊緣,靠近數據生成源頭,從而顯著提高響應速度、降低延遲和帶寬…

項目VS運營

一、項目與運營的定義與區別 項目與運營是企業管理中的兩個重要概念&#xff0c;盡管在實際運作中它們常被視為同義詞&#xff0c;但它們之間存在明顯的區別。 項目&#xff0c;指的是為達到特定目標&#xff0c;通過臨時性、系統性、有計劃的組織、協調、控制等系列活動&…

基于深度學習的端到端語音識別時代

隨著深度學習的發展&#xff0c;語音識別由DNN-HMM時代發展到基于深度學習的“端到端”時代&#xff0c;這個時代的主要特征是代價函數發生了變化&#xff0c;但基本的模型結構并沒有太大變化。總體來說&#xff0c;端到端技術解決了輸入序列長度遠大于輸出序列長度的問題。 采…

Visual Studio中調試信息格式參數:/Z7、/Zi、/ZI參數

一般的調試信息都保存在pdb文件中。 Z7參數表示這些調試信息保存到OBJ目標文件中&#xff0c;這樣的好處是不需要單獨分發PDB文件給下游。Zi就是把所有的調試信息都保存在pdb文件中&#xff0c;以縮小發布文件的大小。ZI和Zi類似&#xff0c;但是增加了熱重載的能力&#xff1…

Django admin后臺創建密文密碼

Django admin后臺創建密文密碼 如題現在有一張用戶表User # user/models.py from django.db import models from django.contrib.auth.models import AbstractUserclass User(AbstractUser):SEX_CHOICES [(0, 男),(1, 女),]sex models.IntegerField(choicesSEX_CHOICES, de…

數據結構:詳解二叉樹(樹,二叉樹順序結構,堆的實現與應用,二叉樹鏈式結構,鏈式二叉樹的4種遍歷方式)

目錄 1.樹的概念和結構 1.1樹的概念 1.2樹的相關概念 1.3樹的代碼表示 2.二叉樹的概念及結構 2.1二叉樹的概念 2.2特殊的二叉樹 2.3二叉樹的存儲結構 2.3.1順序存儲 2.3.2鏈式存儲 3.二叉樹的順序結構和實現 3.1二叉樹的順序結構 3.2堆的概念和結構 3.3堆的特點 3…

k-means聚類算法

在Python中&#xff0c;可以使用scikit-learn庫來實現k-means聚類算法。scikit-learn是一個強大的機器學習庫&#xff0c;提供了許多算法的實現&#xff0c;包括k-means聚類。 以下是使用scikit-learn實現k-means聚類的基本步驟&#xff1a; 安裝scikit-learn&#xff1a; 如果…

一文掌握JavaScript 中類的用法

文章導讀&#xff1a;AI 輔助學習前端&#xff0c;包含入門、進階、高級部分前端系列內容&#xff0c;當前是 JavaScript 的部分&#xff0c;瑤琴會持續更新&#xff0c;適合零基礎的朋友&#xff0c;已有前端工作經驗的可以不看&#xff0c;也可以當作基礎知識回顧。 這篇文章…

SQL常用語句--模糊查詢LIKE

like模糊查詢&#xff0c;支持%和下劃線匹配&#xff0c;%匹配多個字符&#xff0c;_下劃線&#xff1a;任意一個字符&#xff0c;示例&#xff1a; 1&#xff09;查詢名字中含有張的學生信息 select * from student where sname like ‘%張%’&#xff1b; 2&#xff09;查…

MySQL統計字符長度:CHAR_LENGTH(str)

對于SQL表&#xff0c;用于計算字符串中字符數的最佳函數是 CHAR_LENGTH(str)&#xff0c;它返回字符串 str 的長度。 另一個常用的函數 LENGTH(str) 在這個問題中也適用&#xff0c;因為列 content 只包含英文字符&#xff0c;沒有特殊字符。否則&#xff0c;LENGTH() 可能會返…

django使用fetch上傳文件

在上一篇文章中&#xff0c;我包裝了fetch方法&#xff0c;使其攜帶cookie。但是之前fetch傳遞的是json數據&#xff0c;現在有了一個上傳文件的需求&#xff0c;因此需要進行修改&#xff1a; const sendRequest (url, method, data) > {const csrftoken Cookies.get(cs…

discuz如何添加主導航

大家好&#xff0c;今天教大家怎么樣給discuz添加主導航。方法其實很簡單&#xff0c;大家跟著我操作既可。一個網站的導航欄是非常重要的&#xff0c;一般用戶進入網站的第一印象就是看網站的導航欄。如果大家想看效果的話可以搜索下網創有方&#xff0c;或者直接點擊查看效果…

精選免費在線工具與資源推薦20240531

精選免費在線工具與資源推薦 引言 在互聯網高速發展的今天&#xff0c;我們身處一個信息爆炸的時代。為了更好地應對工作和學習中的挑戰&#xff0c;我們時常需要借助各種工具和資源來提高效率。幸運的是&#xff0c;網絡上存在著大量免費且高效的在線工具和資源&#xff0c;…

Google VertexAI API 接入

import vertexai import os #此步非常重要&#xff0c;否則無法訪問&#xff0c;去GCP創建服務賬號密鑰。 os.environ["GOOGLE_APPLICATION_CREDENTIALS"] "服務賬號json格式key" from vertexai.generative_models import GenerativeModel, Part # TO…

嵌入式學習——4——c++ 結構體+類

1、數據類型 基本數據類型&#xff1a;char、int 、float、 double、string、bool 構造數據類型&#xff1a;數組、指針、結構體、共用體、枚舉、類 2、引用 引用就是 別名 數據類型 &引用名 同類型的變量名 &#xff08;&引用符號&#xff09; int a 10;int &…

標準發布 | 反滲透和納濾水處理膜修復再利用技術要求

本文件由浙江大學、中華環保聯合會水環境治理專業委員會提出。 本文件由中華環保聯合會歸口。 本文件主編單位&#xff1a;浙江大學、河南一膜環保技術有限公司、安徽精高水處理有限公司、國能龍源環保有限公司、湖南沁森高科新材料有限公司。 本文件參編單位&#xff1a;深…