最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Qt播放器的實(shí)現(xiàn)詳解(支持Rgb,YUV格式)

 更新時間:2022年12月13日 15:08:58   作者:音視頻開發(fā)老舅  
這篇文章主要為大家詳細(xì)介紹了如何利用Qt實(shí)現(xiàn)簡易的播放器,可以支持支持Rgb,YUV格式。文中的示例代碼講解詳細(xì),感興趣的小伙伴可以嘗試一下

色度空間轉(zhuǎn)換

YUV顏色模型其實(shí)常用于視頻傳輸和圖像壓縮。由于人類的眼睛,對亮度的敏感度遠(yuǎn)超過對色彩的敏感度,所以視頻傳輸過程中,為了減小帶寬,通常將色彩分量 UV的比例減小,以達(dá)到降低帶寬的目的。這就出現(xiàn)了YUV4:4:4、YUV4:2:2、YUV4:1:1等格式。

RGB32使用32位來表示一個像素,RGB分量各用去8位,剩下的8位用作Alpha通道或者不用。(ARGB32就是帶Alpha通道的RGB32。)注意在內(nèi)存中RGB各分量的排列順序?yàn)椋築GRA BGRA BGRA…。通??梢允褂肦GB32數(shù)據(jù)結(jié)構(gòu)來操作一個像素,它的定義為:

typedef struct RGB32 {
BYTE    rgbBlue;      // 藍(lán)色分量
BYTE    rgbGreen;     // 綠色分量
BYTE    rgbRed;       // 紅色分量
BYTE    rgbReserved;  // 保留字節(jié)(用作Alpha通道或忽略)
} RGB32;

YUV轉(zhuǎn)RGB的公式

R = Y + 1.402 * (V-128) G = Y – 0.34413 * (U-128) – 0.71414*(V-128) B= Y + 1.772*(U-128)

對本地RGB32視頻圖像的播放

1、繪圖顯示函數(shù) 打開目錄函數(shù)

void MainWindow ::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setBrush(Qt::black);
    QRect rect = ui->widget_video->geometry();
    painter.drawRect(rect);
 
    if (mImage.size().width() <= 0) return;
    //將圖像按比例縮放成和窗口一樣大小
    QImage img = mImage.scaled(ui->widget_video->size(),Qt::KeepAspectRatio);
    int x = ui->widget_video->width() - img.width();
    int y = ui->widget_video->height() - img.height();
    x /= 2;
    y /= 2;
    x += ui->widget_video->x();
    y += ui->widget_video->y();
    painter.drawImage(QPoint(x,y),img); //畫出圖像
}
/*接收信號函數(shù)傳遞來過的圖像,并準(zhǔn)備執(zhí)行繪畫函數(shù)*/
void MainWindow::slotGetOneFrame(QImage img)
{
    mImage = img;
    update(); //調(diào)用update將執(zhí)行 paintEvent函數(shù)
}
/*打開目錄按鍵的槽函數(shù)*/
void MainWindow::on_pushButton_open_clicked()
{
    QString s = QFileDialog::getOpenFileName(this, "", "視頻絕對路徑","rgb flie(*.rgb);;yuv file(*.yuv)");
    if (!s.isEmpty())
    {
        s.replace("/","\\");
        ui->lineEdit_filepath->setText(s);//將字符串寫入lineEdit_filepath文本框
    }
 
}

2、按開始播放的槽函數(shù)

void MainWindow::on_pushButton_display_clicked()
{
    /*提取三個文本框的內(nèi)容*/
    QString filePath = ui->lineEdit_filepath->text();
    int width = ui->lineEdit_2_width->text().toInt();//toInt()表示將類型轉(zhuǎn)化成int
    int height = ui->lineEdit_height->text().toInt();
  //視頻播放幀數(shù)設(shè)置
    if(ui->fpsBox->currentIndex()==0)//如果下拉框中的數(shù)值是25fps
        mThread->Setfps_25();
    else//否則
        mThread->Setfps_30();
    maxValue=filenumber();//滑動條最大值獲取
    //設(shè)定滑條的范圍,確保滑條的每一步為一幀
    ui->horizontalSlider->setRange(0,maxValue-1);//設(shè)定滑動條的范圍
    mThread->startPlay(filePath,width,height);//啟動線程顯示播放
}

3、啟動線程 進(jìn)行播放

void TransCodeThread::startPlay(QString infile,int width,int height)
{
    mFilePath = infile;
    mWidth = width;
    mHeight = height;
    start();//啟動線程執(zhí)行run()
}
 
/*在獨(dú)立線程中對視頻進(jìn)行解碼,并通過信號函數(shù)sig_GetOneFrame傳送每一幀圖像*/
void TransCodeThread::run()
{
        time.start();
        char filePath[1024]={0};
        strcpy(filePath,mFilePath.toUtf8().data());
        FILE *fp_yuv_rgb = fopen(filePath,"rb");  //打開視頻文件      
        int width = mWidth;
        int height = mHeight;
        if (fp_yuv_rgb == NULL) return;
        /**判斷文件類型**/
        QString fileright = mFilePath.right(3);
        if(fileright =="rgb")
           {
             m_filetype=1;
           }
        else if(fileright =="yuv")
           {
              m_filetype=0;
           }
        //獲取文件的大小
        fseek( fp_yuv_rgb,0,SEEK_END );  //把文件指針定位到文件尾      
        int file_size=ftell( fp_yuv_rgb );//獲取文件的大小
        fseek( fp_yuv_rgb,0,SEEK_SET );//把文件指針指向開頭
 
        int yuvSize = width * height *3/2  ;
        BYTE *yuvBuffer = (BYTE *)malloc(yuvSize);
        int rgbSize = width *height *sizeof(RGB32);//RGB32為一個結(jié)構(gòu)體   32位
        BYTE *rgbBuffer = (BYTE *)malloc(rgbSize);        
        //調(diào)試顯示
         qDebug()<<file_size;
         qDebug()<<maxValue;
        int ReadedSize = 0;//已讀文件大小初始化
        for(int i=0;; i++)
        {
            if (feof(fp_yuv_rgb))//文件讀取結(jié)束
            {
              //qDebug()<<m_i;
              break;
            }
            int readedsize;
            if(isMoved)//按下滑塊,則修改讀取指針的位置
            {
 
                //獲取文件指針的位置(滑條被分為與幀數(shù)同等分)
                int pointPosition = file_size * (double)SliderPosition/maxValue;
                fseek( fp_yuv_rgb, pointPosition , SEEK_SET );
                ReadedSize = pointPosition ;
            }
            if(m_filetype==1)//rgb
            {
                readedsize= fread(rgbBuffer,1,rgbSize,fp_yuv_rgb);//注釋,YUV2RGB
               // qDebug()<<readedsize;
            }
            else//yuv
            {
                readedsize=  fread(yuvBuffer,1,yuvSize,fp_yuv_rgb);//讀取yuv文件
                Yuv420p2Rgb32(yuvBuffer, rgbBuffer, width, height);//轉(zhuǎn)換
            }
             //把這個RGB數(shù)據(jù) 用QImage加載
            QImage tmpImg((uchar *)rgbBuffer,width,height,QImage::Format_RGB32);
            QImage image = tmpImg.copy(); //把圖像復(fù)制一份 傳遞給界面顯示
            if(fps == 25)
            {
                msleep(20);
            }
            else if(fps == 30)
            {
                msleep(10);
            }
            emit sig_GetOneFrame(image);  //發(fā)送信號
            //更新已讀取文件大小,更改滑塊位置
            ReadedSize += readedsize;
            if(!isMoved)
                emit moveSlider(((double)ReadedSize/file_size)*maxValue);//發(fā)送進(jìn)度條移動信號  已讀的比例
            int time_Diff = time.elapsed();//消逝的時間
            float f = time_Diff/1000.0;//秒轉(zhuǎn)換為毫秒
            float TotalTime = 0 ;
            TotalTime += f;//播放的總時間
            QString TT = QString("%1").arg(TotalTime);
            qDebug() << TT;
        }
        //釋放內(nèi)存
        free(yuvBuffer);
        free(rgbBuffer);
}

4、格式轉(zhuǎn)換函數(shù)

void TransCodeThread::Yuv420p2Rgb32(const BYTE *yuvBuffer_in,const BYTE *rgbBuffer_out,int width,int height)
{
    BYTE *yuvBuffer = (BYTE *)yuvBuffer_in;
    RGB32 *rgb32Buffer = (RGB32 *)rgbBuffer_out;
 
    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            int index = y * width + x;
 
            int indexY = y * width + x;
            int indexU = width * height + y / 2 * width / 2 + x / 2;
            int indexV = width * height + width * height / 4 + y / 2 * width / 2 + x / 2;
 
            BYTE Y = yuvBuffer[indexY];
            BYTE U = yuvBuffer[indexU];
            BYTE V = yuvBuffer[indexV];
 
            RGB32 *rgbNode = &rgb32Buffer[index];
 
 
 
            rgbNode->rgbRed = Y + 1.402 * (V-128);
            rgbNode->rgbGreen = Y - 0.34413 * (U-128) - 0.71414*(V-128);
            rgbNode->rgbBlue = Y + 1.772*(U-128);
        }
    }
}

5、實(shí)現(xiàn)進(jìn)度條與暫停的各類函數(shù)

//獲取視頻幀數(shù)
int  MainWindow::filenumber()
{
    /*提取三個文本框的內(nèi)容*/
    QString filePath = ui->lineEdit_filepath->text();
    int width = ui->lineEdit_2_width->text().toInt();//toInt()表示將類型轉(zhuǎn)化成int
    int height = ui->lineEdit_height->text().toInt();   
    char curfilePath[1024]={0};
    strcpy(curfilePath,filePath.toUtf8().data());
    FILE *fp_yuv_rgb = fopen(curfilePath,"rb");
    //文件指針移到文件尾
    fseek( fp_yuv_rgb,0,SEEK_END );
    //獲取文件的大小
    int file_size=ftell( fp_yuv_rgb );
 
    int yuvSize = width * height * 3/2  ;
    int rgbSize = width *height *sizeof(RGB32);
    /**計(jì)算幀數(shù) 判斷文件類型**/
    QString fileright = filePath.right(3);
    static int number;
    if(fileright =="rgb")
       {
          number = file_size/rgbSize;
       }
    else if(fileright =="yuv")
       {
          number = file_size/yuvSize;
       }
     return number;
}
//改變滑塊位置的槽函數(shù)
void MainWindow::ChangeSliderPosition(int position)
{  
    ui->horizontalSlider->setValue(position);   
}
 
//滑塊按下槽函數(shù)
void MainWindow::on_horizontalSlider_sliderPressed()
{
    //qDebug()<<"anxia ";
    mThread->isMoved = true;
}
//滑塊移動槽函數(shù)  實(shí)時獲取滑塊的位置
void MainWindow::on_horizontalSlider_sliderMoved(int position)
{
    mThread->SliderPosition = position;
}
// 滑塊松開槽函數(shù)
void MainWindow::on_horizontalSlider_sliderReleased()
{
    mThread->isMoved = false;
}
//暫停按鈕槽函數(shù)
void MainWindow::on_pushButton_pause_clicked()
{
    mThread->SliderPosition = ui->horizontalSlider->value();
    mThread->isMoved = !mThread->isMoved;
}

6、各類槽函數(shù)的連接

/*構(gòu)造函數(shù)*/
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);//創(chuàng)建ui頁面
    mThread = new TransCodeThread;//創(chuàng)建類對象
 
    /*槽與信號鏈接*/
    connect(mThread,SIGNAL(sig_GetOneFrame(QImage)),this,SLOT(slotGetOneFrame(QImage)));//進(jìn)行圖像傳遞和接收
    connect(mThread,&TransCodeThread::moveSlider, this, &MainWindow::ChangeSliderPosition);
}
 
/*析構(gòu)函數(shù)*/
MainWindow::~MainWindow()
{
    delete ui;//刪除ui界面
}

以上就是基于Qt播放器的實(shí)現(xiàn)詳解(支持Rgb,YUV格式)的詳細(xì)內(nèi)容,更多關(guān)于Qt播放器的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C++類中的繼承實(shí)例詳解

    C++類中的繼承實(shí)例詳解

    這篇文章主要介紹了C++類中的繼承實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-07-07
  • 關(guān)于C語言操作符的那些事(超級全)

    關(guān)于C語言操作符的那些事(超級全)

    這篇文章主要給大家介紹了關(guān)于C語言操作符的那些事兒,c語言的操作符有很多,包括算術(shù)操作符、移位操作符、位操作符、賦值操作符、單目操作符、關(guān)系操作符、邏輯操作符、條件操作符、逗號表達(dá)式、下標(biāo)引用、函數(shù)調(diào)用和結(jié)構(gòu)成員,需要的朋友可以參考下
    2021-08-08
  • C語言數(shù)據(jù)結(jié)構(gòu)中數(shù)制轉(zhuǎn)換實(shí)例代碼

    C語言數(shù)據(jù)結(jié)構(gòu)中數(shù)制轉(zhuǎn)換實(shí)例代碼

    這篇文章主要介紹了C語言數(shù)據(jù)結(jié)構(gòu)中數(shù)制轉(zhuǎn)換實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • VS2019開發(fā)Linux C++程序的實(shí)現(xiàn)步驟

    VS2019開發(fā)Linux C++程序的實(shí)現(xiàn)步驟

    由于很多unix特有的函數(shù)無法在Windows上使用,而Vim又用的不太順手,突然想到最初用vs的時候有一個基于Linux的C++開發(fā)。本文就來介紹一下,感興趣的可以了解一下
    2021-07-07
  • 談?wù)剉ector的特殊性之為什么它不是STL容器

    談?wù)剉ector的特殊性之為什么它不是STL容器

    這篇文章主要給大家介紹了關(guān)于vector的特殊性之為什么它不是STL容器的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用c++具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • C語言中野指針和空指針的區(qū)別

    C語言中野指針和空指針的區(qū)別

    本文主要介紹了野指針和空指針的概念、用途、原理,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-11-11
  • C語言如何計(jì)算字符串長度

    C語言如何計(jì)算字符串長度

    這篇文章主要介紹了C語言如何計(jì)算字符串長度問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • C語言如何在字符數(shù)組中插入一個字符

    C語言如何在字符數(shù)組中插入一個字符

    這篇文章主要介紹了C語言如何在字符數(shù)組中插入一個字符,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • linux中查詢dns示例

    linux中查詢dns示例

    這篇文章主要介紹了linux中查詢dns示例,需要的朋友可以參考下
    2014-04-04
  • C/C++中多重繼承詳解及其作用介紹

    C/C++中多重繼承詳解及其作用介紹

    這篇文章主要介紹了C/C++中多重繼承詳解及其作用介紹,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09

最新評論

五华县| 缙云县| 固阳县| 唐海县| 奉节县| 兴宁市| 清远市| 海安县| 台东县| 陆河县| 杂多县| 福建省| 巴楚县| 长沙市| 仪陇县| 渝北区| 朔州市| 宜良县| 大石桥市| 桐柏县| 林周县| 九台市| 如东县| 桓台县| 来宾市| 高陵县| 汽车| 宜阳县| 砚山县| 洮南市| 万年县| 常宁市| 大洼县| 天津市| 曲水县| 吉首市| 建湖县| 灌云县| 屯昌县| 淄博市| 吉首市|