FFPLAY的原理(二)

關于包Packets的注釋

從技術上講一個包可以包含部分或者其它的數據,但是ffmpeg的解釋器保證了我們得到的包Packets包含的要么是完整的要么是多種完整的幀。

現在我們需要做的是讓SaveFrame函數能把RGB信息定稿到一個PPM格式的文件中。我們將生成一個簡單的PPM格式文件,請相信,它是可以工作的。

void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame) {

FILE *pFile;

char szFilename[32];

int y;

// Open file

sprintf(szFilename, "frame%d.ppm", iFrame);

pFile=fopen(szFilename, "wb");

if(pFile==NULL)

return;

// Write header

fprintf(pFile, "P6/n%d %d/n255/n", width, height);

// Write pixel data

for(y=0; y<height; y++)

fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile);

// Close file

fclose(pFile);

}

我們做了一些標準的文件打開動作,然后寫入RGB數據。我們一次向文件寫入一行數據。PPM格式文件的是一種包含一長串的RGB數據的文件。如果你了解 HTML色彩表示的方式,那么它就類似于把每個像素的顏色頭對頭的展開,就像#ff0000#ff0000....就表示了了個紅色的屏幕。(它被保存成二進制方式并且沒有分隔符,但是你自己是知道如何分隔的)。文件的頭部表示了圖像的寬度和高度以及最大的RGB值的大小。

現在,回顧我們的main()函數。一旦我們開始讀取完視頻流,我們必需清理一切:

// Free the RGB image

av_free(buffer);

av_free(pFrameRGB);

// Free the YUV frame

av_free(pFrame);

// Close the codec

avcodec_close(pCodecCtx);

// Close the video file

av_close_input_file(pFormatCtx);

return 0;

你會注意到我們使用av_free來釋放我們使用avcode_alloc_fram和av_malloc來分配的內存。

上面的就是代碼!下面,我們將使用Linux或者其它類似的平臺,你將運行:

gcc -o tutorial01 tutorial01.c -lavutil -lavformat -lavcodec -lz -lavutil -lm

如果你使用的是老版本的ffmpeg,你可以去掉-lavutil參數:

gcc -o tutorial01 tutorial01.c -lavutil -lavformat -lavcodec -lz -lm

大多數的圖像處理函數可以打開PPM文件。可以使用一些電影文件來進行測試。

輸出到屏幕

SDL和視頻

為了在屏幕上顯示,我們將使用SDL.SDL是Simple Direct Layer的縮寫。它是一個出色的多媒體庫,適用于多平臺,并且被用在許多工程中。你可以從它的官方網站的網址 http://www.libsdl.org/ 上來得到這個庫的源代碼或者如果有可能的話你可以直接下載開發包到你的操作系統中。按照這個指導,你將需要編譯這個庫。(剩下的幾個指導中也是一樣)

SDL庫中有許多種方式來在屏幕上繪制圖形,而且它有一個特殊的方式來在屏幕上顯示圖像――這種方式叫做YUV覆蓋。YUV(從技術上來講并不叫 YUV而是叫做YCbCr)是一種類似于RGB方式的存儲原始圖像的格式。粗略的講,Y是亮度分量,U和V是色度分量。(這種格式比RGB復雜的多,因為很多的顏色信息被丟棄了,而且你可以每2個Y有1個U和1個V)。SDL的YUV覆蓋使用一組原始的YUV數據并且在屏幕上顯示出他們。它可以允許4種不同的 YUV格式,但是其中的YV12是最快的一種。還有一個叫做YUV420P的YUV格式,它和YV12是一樣的,除了U和V分量的位置被調換了以外。 420意味著它以4:2:0的比例進行了二次抽樣,基本上就意味著1個顏色分量對應著4個亮度分量。所以它的色度信息只有原來的1/4。這是一種節省帶寬的好方式,因為人眼感覺不到這種變化。在名稱中的P表示這種格式是平面的――簡單的說就是Y,U和V分量分別在不同的數組中。FFMPEG可以把圖像格式轉換為YUV420P,但是現在很多視頻流的格式已經是YUV420P的了或者可以被很容易的轉換成YUV420P格式。

于是,我們現在計劃把指導1中的SaveFrame()函數替換掉,讓它直接輸出我們的幀到屏幕上去。但一開始我們必需要先看一下如何使用SDL庫。首先我們必需先包含SDL庫的頭文件并且初始化它。

#include <SDL.h>

#include <SDL_thread.h>

if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {

fprintf(stderr, "Could not initialize SDL - %s/n", SDL_GetError());

exit(1);

}

SDL_Init()函數告訴了SDL庫,哪些特性我們將要用到。當然SDL_GetError()是一個用來手工除錯的函數。

創建一個顯示

現在我們需要在屏幕上的一個地方放上一些東西。在SDL中顯示圖像的基本區域叫做面surface。

SDL_Surface *screen;

screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0);

if(!screen) {

fprintf(stderr, "SDL: could not set video mode - exiting/n");

exit(1);

}

這就創建了一個給定高度和寬度的屏幕。下一個選項是屏幕的顏色深度――0表示使用和當前一樣的深度。(這個在OS X系統上不能正常工作,原因請看源代碼)

現在我們在屏幕上來創建一個YUV覆蓋以便于我們輸入視頻上去:

SDL_Overlay *bmp;

bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height,

SDL_YV12_OVERLAY, screen);

正如前面我們所說的,我們使用YV12來顯示圖像。

顯示圖像

前面那些都是很簡單的。現在我們需要來顯示圖像。讓我們看一下是如何來處理完成后的幀的。我們將原來對RGB處理的方式,并且替換 SaveFrame() 為顯示到屏幕上的代碼。為了顯示到屏幕上,我們將先建立一個AVPicture結構體并且設置其數據指針和行尺寸來為我們的YUV覆蓋服務:

if(frameFinished) {

SDL_LockYUVOverlay(bmp);

AVPicture pict;

pict.data[0] = bmp->pixels[0];

pict.data[1] = bmp->pixels[2];

pict.data[2] = bmp->pixels[1];

pict.linesize[0] = bmp->pitches[0];

pict.linesize[1] = bmp->pitches[2];

pict.linesize[2] = bmp->pitches[1];

// Convert the image into YUV format that SDL uses

img_convert(&pict, PIX_FMT_YUV420P,

(AVPicture *)pFrame, pCodecCtx->pix_fmt,

pCodecCtx->width, pCodecCtx->height);

SDL_UnlockYUVOverlay(bmp);

}

首先,我們鎖定這個覆蓋,因為我們將要去改寫它。這是一個避免以后發生問題的好習慣。正如前面所示的,這個AVPicture結構體有一個數據指針指向一個有4個元素的指針數據。由于我們處理的是YUV420P,所以我們只需要3個通道即只要三組數據。其它的格式可能需要第四個指針來表示alpha通道或者其它參數。行尺寸正如它的名字表示的意義一樣。在YUV覆蓋中相同功能的結構體是像素pixel和程度pitch。(程度pitch是在SDL里用來表示指定行數據寬度的值)。所以我們現在做的是讓我們的覆蓋中的pict.data中的三個指針有一個指向必要的空間的地址。類似的,我們可以直接從覆蓋中得到行尺寸信息。像前面一樣我們使用img_convert來把格式轉換成PIX_FMT_YUV420P。

繪制圖像

但我們仍然需要告訴SDL如何來實際顯示我們給的數據。我們也會傳遞一個表明電影位置、寬度、高度和縮放大小的矩形參數給SDL的函數。這樣,SDL為我們做縮放并且它可以通過顯卡的幫忙來進行快速縮放。

SDL_Rect rect;

if(frameFinished) {

// Convert the image into YUV format that SDL uses

img_convert(&pict, PIX_FMT_YUV420P,

(AVPicture *)pFrame, pCodecCtx->pix_fmt,

pCodecCtx->width, pCodecCtx->height);

SDL_UnlockYUVOverlay(bmp);

rect.x = 0;

rect.y = 0;

rect.w = pCodecCtx->width;

rect.h = pCodecCtx->height;

SDL_DisplayYUVOverlay(bmp, &rect);

}

讓我們再花一點時間來看一下SDL的特性:它的事件驅動系統。SDL被設置成當你在SDL中點擊或者移動鼠標或者向它發送一個信號它都將產生一個事件的驅動方式。如果你的程序想要處理用戶輸入的話,它就會檢測這些事件。你的程序也可以產生事件并且傳遞給SDL事件系統。當使用SDL進行多線程編程的時候,這相當有用,這方面代碼我們可以在指導4中看到。在這個程序中,我們將在處理完包以后就立即輪詢事件。現在而言,我們將處理SDL_QUIT事件以便于我們退出:

SDL_Event event;

av_free_packet(&packet);

SDL_PollEvent(&event);

switch(event.type) {

case SDL_QUIT:

SDL_Quit();

exit(0);

break;

default:

break;

}

讓我們去掉舊的冗余代碼,開始編譯。如果你使用的是Linux或者其變體,使用SDL庫進行編譯的最好方式為:

gcc -o tutorial02 tutorial02.c -lavutil -lavformat -lavcodec -lz -lm /

`sdl-config --cflags --libs`

這里的sdl-config命令會打印出用于gcc編譯的包含正確SDL庫的適當參數。為了進行編譯,在你自己的平臺你可能需要做的有點不同:請查閱一下SDL文檔中關于你的系統的那部分。一旦可以編譯,就馬上運行它。

當運行這個程序的時候會發生什么呢?電影簡直跑瘋了!實際上,我們只是以我們能從文件中解碼幀的最快速度顯示了所有的電影的幀。現在我們沒有任何代碼來計算出我們什么時候需要顯示電影的幀。最后(在指導5),我們將花足夠的時間來探討同步問題。但一開始我們會先忽略這個,因為我們有更加重要的事情要處理:音頻!

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

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

相關文章

python生成requirements.txt的兩種方法

python項目如何在另一個環境上重新構建項目所需要的運行環境依賴包&#xff1f; 使用的時候邊記載是個很麻煩的事情&#xff0c;總會出現遺漏的包的問題&#xff0c;這個時候手動安裝也很麻煩&#xff0c;不能確定代碼報錯的需要安裝的包是什么版本。這些問題&#xff0c;requi…

node.js 安裝使用http-server

node.js npm全局安裝了http-server后我該怎么使用它&#xff1f;我在它的安裝目錄下創建了inde.html&#xff0c;瀏覽器localhost:8080可以訪問&#xff0c;那我的項目需要放在它的安裝目錄下&#xff1f;還是需要在我的項目下配置什么或者使用什么指令啟動它&#xff1f;我在我…

D - 卿學姐與魔法

卿學姐與魔法 Time Limit: 1200/800MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submit Status“你的膜法也救不了你 在去拯救公主的道路上&#xff0c;卿學姐披荊斬棘&#xff0c;刀刃早已銹跡斑斑。 一日卿學姐正在為武器的問題發愁&#xff0c;碰到了正…

python對excel表統計視頻教程_Python實現對excel文件列表值進行統計的方法

本文實例講述了Python實現對excel文件列表值進行統計的方法。分享給大家供大家參考。具體如下&#xff1a;#!/usr/bin/env python#codinggbk#此PY用來統計一個execl文件中的特定一列的值的分類import win32com.clientfilenameraw_input("請輸入要統計文件的詳細地址&#…

mooc后臺管理系統設計

摘 要 本設計采用Python中的Django框架實現Mooc后臺管理界面設計,django是一個完整的開源web開源框架,使用起來能夠快速的搭建你想要的網站,由于django自帶后臺管理系統,本設計中后臺管理模板采用功能更加強大的Xadmin實現。數據庫部分采用mysql5.7,由于django中有自帶封裝的數…

DirectShow系統初級指南

流媒體的處理&#xff0c;以其復雜性和技術性&#xff0c;一向廣受工業界的關注。特別伴隨著因特網的普及&#xff0c;流媒體在網絡上的廣泛應用&#xff0c;怎樣使流媒體的處理變得簡單而富有成效逐漸成為了焦點問題。選擇一種合適的應用方案&#xff0c;事半功倍。此時&#…

正則正整數含0

^0?$|^([1-9][0-9]*)?$

MySQL 數據庫導出導入操作

有時需要將 MySQL 數據庫中的數據導入到其它的數據庫中&#xff0c;這里以從 Ubuntu 系統的 MySQL 數據庫導出 zabbix 這個數據庫到 Windows 系統中的MySQL 為例。 導出數據庫 導出數據其實非常方便&#xff0c;比如將 MySQL 中的 zabbix 這個數據庫導出到當前文件夾&#xff…

您的apple id 暫時不符合使用此應用程序_Mac相機不工作時該怎么辦

蘋果公司的許多臺式機和筆記本電腦都包含一個內置網絡攝像頭&#xff0c;該公司愉快地將其稱為FaceTime相機。但是&#xff0c;如果您的Mac網絡攝像頭無法正常工作&#xff0c;并且在嘗試訪問它時顯示為斷開連接或不可用&#xff0c;則您可能不會感到高興。您可以嘗試以下操作來…

基于DirectShow的流媒體解碼和回放

一、 前言  流媒體的定義很廣泛&#xff0c;大多數時候指的是把連續的影像和聲音信息經過壓縮處理后放上網站服務器&#xff0c;讓用戶一邊下載一邊觀看、收聽&#xff0c;而不需要等整個壓縮文件下載到自己機器就可以觀看的視頻/音頻傳輸、壓縮技術。流媒體也指代由這種技術…

《知易行難》擴展練習

在學習了《知易行難》后&#xff0c;這個是一個選做的擴展練習&#xff0c;但是里面的問題真的的很好&#xff0c;所以我也將在這里真實的分享&#xff0c;但是有些敏感的人名我就隱去了。 1. 這一年你做了些什么事情&#xff1f; 1&#xff09;團隊的整合&#xff0c;將團隊…

python 裁判文書網_python - 用selenium模擬登陸裁判文書網,系統報錯找不到元素。...

問 題from selenium import webdriverfrom selenium.webdriver.common.desired_capabilities import DesiredCapabilitiesdcap dict(DesiredCapabilities.PHANTOMJS)dcap["phantomjs.page.settings.userAgent"]("Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWeb…

Python 四大主流 Web 編程框架

目前Python的網絡編程框架已經多達幾十個&#xff0c;逐個學習它們顯然不現實。但這些框架在系統架構和運行環境中有很多共通之處&#xff0c;本文帶領讀者學習基于Python網絡框架開發的常用知識,及目前的4種主流Python網絡框架&#xff1a;Django、Tornado、Flask、Twisted。 …

汕頭市隊賽 SRM16 T2

描述 貓和老鼠&#xff0c;看過吧&#xff1f;貓來了&#xff0c;老鼠要躲進洞里。在一條數軸上&#xff0c;一共有n個洞&#xff0c;位置分別在xi&#xff0c;能容納vi只老鼠。一共有m只老鼠位置分別在Xi&#xff0c;要躲進洞里&#xff0c;問所有老鼠跑進洞里的距離總和最小是…

基于django和vue的xdh官網設計

前言 本項目是使用三段分離的設計 前臺 使用materialize框架搭建的前臺頁面,后端使用的django寫的接口 后臺 使用Amazon UI 模板搭建的界面,管理各個部分的內容 項目環境 python3.7.2 django2.2.9 vue axios jQuery materialize mysql摘 要 本設計采用前后端分離的設計…

C#調用WebService實例和開發(轉)

http://www.cnblogs.com/peterpc/p/4628441.html 一、基本概念 Web Service也叫XML Web Service WebService是一種可以接收從Internet或者Intranet上的其它系統中傳遞過來的請求&#xff0c;輕量級的獨立的通訊技術。是:通過SOAP在Web上提供的軟件服務&#xff0c;使用WSDL文件…

智能情緒分析技術_簡單分析人工智能的表現在計算機網絡應用技術中的優勢

簡單分析人工智能的表現在計算機網絡應用技術中的優勢大數據時代背景下&#xff0c; 計算機網絡技術迅猛發展&#xff0c; 而人工智能技術的發展也進一步推動了計算機網絡技術的發展&#xff0c; 兩者相互融合&#xff0c; 相互促進&#xff0c; 實現了雙贏發展。從人工智能技術…

隨筆:關于關于

突然感覺挺累的。 我愛你。 北京&#xff0c;加油。轉載于:https://www.cnblogs.com/zhengzeze/p/7448878.html

MV預測過程詳解

第一步&#xff1a;確定相鄰塊 MV 預測以宏塊分割&#xff08;或亞宏塊分割&#xff0c;如果宏塊存在亞分割&#xff09;為單位&#xff0c;同一個宏塊分割&#xff08;或亞宏塊分割&#xff09;內所有 4*4 塊 MV 預測值相同。以每個宏塊分割&#xff08;或亞宏塊分割&…

Django models中關于blank與null的補充說明

建立一個簡易Model class Person(models.Model):GENDER_CHOICES((1,Male),(2,Female),)namemodels.CharField(max_length30,uniqueTrue,verbose_name姓 名) birthdaymodels.DateField(blankTrue,nullTrue)gendermodels.IntegerField(choicesGENDER_CHOICES)accountmodels.In…