1. 程式人生 > >在海思hi3516C上面做流媒體rtsp server,總是存在延時很大並且VLC播放丟幀

在海思hi3516C上面做流媒體rtsp server,總是存在延時很大並且VLC播放丟幀

丟幀是VLC報出來的,如下:

我將幀率設定為15,而且是CIF解析度,區域網傳輸,不應該有丟幀啊!?我XX

查了一整天,各種辦法,最後我發現是海思SDK送出來PTS有問題:

pts=pstStream->pstPack[i].u64PTS*90/1000;      //ms*90

乾脆換成我自己計算PTS:

gVideoPath[ch].VencOutQue[wp].u64PTS=gVideoPath[ch].seq*gVencIn[ch].pts_tick;

這樣就不丟幀了,延時也正常了。

但剛開始時,仍然要丟幾幀。

不過仔細聽起來,這種做法,聲音總是一頓一頓的,不連續。

沒有辦法,還是得用SDK提供出來timestamp。而且,越播延遲越大,但第一路流1080P就不會,這TMD究竟是什麼原因啊?

我在海思底層MPP上面配置了三個通道(1080P/720P/QVGA):

   VpssGrp = 0;   VpssChn = 3;

   VencGrp = 0;   VencChn = 0;             //for HD recording

   s32Ret = _COMM_VENC_Start(VencGrp, VencChn, pVideo+0);

   s32Ret = SAMPLE_COMM_VENC_BindVpss(VencGrp, VpssGrp, VpssChn);

   VpssGrp = 0;        VpssChn = 4;

   VencGrp = 1;    VencChn = 1;           //for preview

   s32Ret = _COMM_VENC_Start(VencGrp, VencChn, pVideo+1);

   s32Ret = SAMPLE_COMM_VENC_BindVpss(VencChn, VpssGrp, VpssChn);

   VpssGrp = 0;        VpssChn = 5;

   VencGrp = 2;    VencChn = 2;    //for CIF clip recording

   s32Ret = _COMM_VENC_Start(VencGrp, VencChn, (pVideo+2));

現在的現象就是1080P這個通道是正常的,延遲在2s左右,丟幀也少。720P/QVGA就不行了,延時達到6秒以上,丟幀嚴重。

下面只有兩個辦法:

1、 換成wis-streamer。

2、 錄影為mp4檔案播放,看是否有問題。

我把VpssChn改了一下,不再關聯3/4/5,而是關聯0,這樣的話,延時的問題基本上算是解決了。但是,丟幀的原因始終沒有找到。

我去掉audio後,Video就不再丟幀了,看來,這是音視訊不同步引發的血案啊!

Hi3518平臺流媒體伺服器的音視訊同步問題

PTS:Presentation Time Stamp
DTS:Decoding TimeStamp
PCR:Program ClockReference
STC:System TimeClock

我也正在研究這一塊.說解碼才得到的都是不對的.其實是從LIVE555那裡得到的.afterGettingFrame裡面有一個引數是presentationTime.通過RTSP得到的流的PTS都是由它計算出來的.不過它的單位是us.還是90000.這個要值得注意.ffmpeg解碼後只是校準了PTS.PTS真正的源頭是RTSP的傳送方.只有傳送方才有能力告訴你資料採集的PTS從而幫助你進行同步.

RTP規範裡,RTP包的TIMESTAMP欄位應該指示影象的顯示時間,而且時間單位是tick.像視訊的話單位就是90K,那一段25fps的視訊每增長一幀,時間戳就應該增加3600.但是同樣是通過RTSP播實時流,ffplay和vlc對於時間戳的處理是不一樣的.如果在ffplay裡.它直接把rtp包裡的timestamp當作是解碼前的pts傳入avcodec_decode_video2().ffmpeg進行重排序(如果沒有B幀,一般是原樣複製到解碼後的AVFrame裡),然後將它乘以1/90K還原成us的單位,然後直接用來usleep();而vlc的rtsp傳輸模組用的是live555,live555在我看來多此一舉了,它對上層遮蔽了RTP包裡的TIMESTAMP.而是直接幫你還原好了.單位就是us.也就是說,afterGettingFrame()函式的pts單位是us.可以直接拿來用usleep了。

// 1s = 90000 time scale , 一幀就應該是  90000/video_frame_rate 個timescale
static uint32_t video_frame_rate = 30;
static uint32_t video_pts_increment = 90000 / video_frame_rate;   //用一秒鐘除以幀率,得到每一幀應該耗時是多少,單位是 timescale單位
static uint64_t video_pts = 0;
pts初始值可以是任意的,我一般定為0,後面每一幀加上增量就可以了。
音訊pts的計算方法同上,只不過不是通過幀率,而是通過取樣率。
uint32_t audio_pts_increment = (90000 * audio_samples_per_frame) / audio_sample_rate;
audio_samples_per_frame這個值對aac和mp3是不同的,aac固定為1024,mp3固定為1152。

>>

用了你的計算方法,音視訊可以用VLC同時播放,但是音訊過一段時間後就變慢了。
而且越來延時越大,最後音訊就沒有了。請問知道是什麼原因嗎?而且這是變幀率,根本不應該這樣來計算。

A:RFC3984 規定採用 90000 Hz 的時鐘,因此如果編碼幀頻是 30,那麼時間戳間隔就該是 90000 / 30 = 3000。audio_timebase =av_q2d(fmtctx->streams[audio_index]->time_base);
video_timebase = av_q2d(fmtctx->streams[video_index]->time_base);
last_video_pts = pts * video_timebase;
last_audio_pts = pts * audio_timebase;
timebase就是單位
以audio為基準同步video(演算法是如何?),因為audio是固定幀率的,而video是變幀率。只要設定好了 ao 的引數,如sample rate, channels, sample size等, audio驅動就能以正確的速度播放,所以只要程式裡write不出大問題的話,這種同步是非常有效的。

一 固定幀率

1. 視訊時間戳

     pts = inc++*(1000/fps);  其中inc是一個靜態的,初始值為0,每次打完時間戳inc加1.

    在ffmpeg,中的程式碼

    pkt.pts=m_nVideoTimeStamp++ * (m_VCtx->time_base.num * 1000 /m_VCtx->time_base.den);

 2. 音訊時間戳

    pts = inc++ *(frame_size * 1000 / sample_rate)

   在ffmpeg中的程式碼為

   pkt.pts=m_nAudioTimeStamp++ * (m_ACtx->frame_size * 1000 / m_ACtx->sample_rate);

取樣頻率是指將模擬聲音波形進行數字化時,每秒鐘抽取聲波幅度樣本的次數。

。正常人聽覺的頻率範圍大約在20Hz~20kHz之間,根據奈奎斯特取樣理論,為了保證聲音不失真,取樣頻率應該在40kHz左右。常用的音訊取樣頻率有8kHz、11.025kHz、22.05kHz、16kHz、37.8kHz、44.1kHz、48kHz等,如果採用更高的取樣頻率,還可以達到DVD的音質

對取樣率為44.1kHz的AAC音訊進行解碼時,一幀的解碼時間須控制在23.22毫秒內。

背景知識:

(一個AAC原始幀包含一段時間內1024個取樣及相關資料)
分析:

1 AAC

音訊幀的播放時間=一個AAC幀對應的取樣樣本的個數/取樣頻率(單位為s)

一幀 1024個 sample。取樣率 Samplerate 44100KHz,每秒44100個sample, 所以 根據公式   音訊幀的播放時間=一個AAC幀對應的取樣樣本的個數/取樣頻率

當前AAC一幀的播放時間是= 1024*1000000/44100=22.32ms(單位為ms)

2 MP3

 mp3 每幀均為1152個位元組, 則:

frame_duration = 1152 * 1000000 /sample_rate

例如:sample_rate= 44100HZ時, 計算出的時長為26.122ms,這就是經常聽到的mp3每幀播放時間固定為26ms的由來。

二 可變幀率

有很多的採集卡,攝像頭,在做採集的時候,明明設定的25FPS,但實際採集資料回撥過來,發現並不是40毫秒的間隔,而是50,60,甚至100不等的時間間隔。

這就給編碼後打時間戳帶來很大的困難。

在libav裡,我們的預設編碼引數都是:

ptAvEncoder->ptAvStreamVideo->codec->time_base.den = s32Fps;

ptAvEncoder->ptAvStreamVideo->codec->time_base.num = 1;

這樣在編碼後的時間戳以1遞增,只適合於固定幀率。

我們來改一下:

ptAvEncoder->ptAvStreamVideo->codec->time_base.den = s32Fps * 1000;

ptAvEncoder->ptAvStreamVideo->codec->time_base.num = 1* 1000;

這樣就把時間戳的scale變成了毫秒,就可以以毫秒為單位進行計算了,如下:

tAvPacket.pts = ((s64)u32TimeStamp * (s64)s32Fps);

u32TimeStamp是從開始記錄的時間差值,以毫秒為單位;s32Fps是幀率。

對於音訊,mp4檔案預設是取樣率為tick的,時間戳計算為:

tAvPacket.pts = (AvEncoderAudioInSizeGet(hHandle) * ( (s64)(u32TimeStamp)) / (AvEncoderAudioInSizeGet(hHandle) * 1000 / ptAvEncoder->ptAvStreamAudio->codec->sample_rate);

AvEncoderAudioInSizeGet(hHandle) 每次編碼器需要的PCM資料長度。

u32TimeStamp是從開始記錄的時間差值,以毫秒為單位。

 ptAvEncoder->ptAvStreamAudio->codec->sample_rate PCM取樣率,代表一秒的資料量。

因為乘以了1000,所以也化成了毫秒單位。

一般有三種辦法
1.以音訊為主進行同步
2.以視訊為主進行同步
3.以一個外部參考時鐘為同步
你可以參考下ffmpeg下的ffplay來做,還有
http://www.dranger.com/ffmpeg/tutorial05.html 和
http://www.dranger.com/ffmpeg/tutorial04.html 
具體如何實現還是要靠自己研究清楚程式碼後來解決的.

同步的方法:

1、 audio pts直接用video的pts,這樣的話,播放繼續,Video受audio拖累而丟包嚴重。

2、 video pts直接用audio pts,結果Video播放不動,audio可以繼續。

3、 audio pts直接填0,也就是不要,這樣播放是最為流暢的,但video偶爾有丟幀,不知道是否受audio的拖累。

相關推薦

hi3516C上面媒體rtsp server總是存在並且VLC播放

丟幀是VLC報出來的,如下: 我將幀率設定為15,而且是CIF解析度,區域網傳輸,不應該有丟幀啊!?我XX 查了一整天,各種辦法,最後我發現是海思SDK送出來PTS有問題: pts=pstStream->pstPack[i].u64PTS*90/100

雲遊戲媒體整體架構設計(雲遊戲媒體技術前瞻最近雲遊戲概念加之對流媒體技術略有研究簡單寫一些)

前言:遙想當年阿法狗戰敗一眾圍棋國手,風氣一轉,似乎所有人都懂AI。這次谷歌又放出了stadia,國內鵝廠再次跑步進場,貴州某xx雲提前佈局。閒來無事,嘗試體驗了一下貴州某xx雲的雲遊戲(不打廣告),暫且不評論如何如何,剛好對流媒體技術略有研究,僅在這裡簡單聊一下這方面涉及的架構和技術。架構設計:總體架構自上

Nginx媒體服務Windows版實現直播

宣告:網上有很多關於Linux系統的配置,這裡就不記錄了。剛開始搭建直播室,用的是Java語言, Java開源的流媒體服務有Red5,但是很久沒更新了,而且文件較少不容易上手,對於直播功能相對要求較低的還是選擇ngin來搭建流媒體服務,下面是記錄搭建步驟。 一、下載搭建時需要用到的軟體 1、下載 ngi

NGINX和FFMPEG 媒體伺服器。

NGINX和FFMPEG 做流媒體伺服器。 啟動命令 nginx.exe -c conf\nginx-iptv.conf ffmpeg -re -i “http://dcte1.***.cn:8880/live/cctv1/index.m3u8” -f flv -r 25 -s

3511上面實現wifi模組變成ap站點功能+wifi rt3070驅動的移植

參照了網上的無數部落格,結合自己的開發板,終於在海思3511開發板上面實現wifi模組變ap站的功能。首先開發板裡面沒有支援ap功能的驅動,這個就需要手工移植。整體的步驟都大同小異,主要是平臺的差異,導致移植時候出現的

android使用MediaPlayer類播放媒體RTSP(實時協議)

實時流協議RTSP(Real-Time Streaming Protocol)是IETF提出的協議,對應的RFC文件為RFC2362。 RTSP地址,如:rtsp://www.www.com/aaaa/file.sdp 在android下使用 MediaPlayer播放,支

VLC和Qt結合編寫媒體rtsp播放

      VLC播放器是一款功能強大且小巧的播放器,它支援多種多樣的音視訊格式,比如MPEG1,2以及mp3等等。並且通過Qt和VLC的結合能讓每個開發者寫出自己的視訊流媒體播放器。     Qt與VLC結合編寫流媒體播放器主要有兩種辦法:       一. 通過V

媒體視訊搬運並沒有大家所想的那麼難

之所以建議大家去做自媒體視訊搬運,是因為: a.原創和垂直細分是日後內容創業的大方向,如今提前佔位很重要 b.原創的文章或是自媒體視訊搬運更容易建立個人內容品牌,能夠持久賺錢,越賺越多 c.取得原創的文章或是自媒體視訊搬運,收益更高。如,沒有拿到原創的短視訊,每萬次播放的收益是2

直播技術總結(一)媒體伺服器搭建進行推

前言:直播技術,近年來,相當火,先且不說Codec部分,那它到底複雜麼? 服務端推流,客戶端進行拉流,兩者結合,變成直播,應該說如何優化直播的實時性中的問題,才是複雜部分,如網路原因,如視訊卡頓等。今天介紹直播技術總結中流媒體伺服器搭建,進行推流,用Mac搭

osd+freetype+SDL+SDL_ttf編譯成功後Makefile的編寫

arm-hisiv400-linux-gcc -Wall -g `sdl-config --cflags --libs` -I/home/ach/Hi3516A_SDK_V2.0.7.0/mpp/sample/achcamapp/../common -I/opt/sdl_lib/include -I/opt

EasyPlayer-RTSP-Android安卓播放播放RTSP延遲優化策略極低

EasyPlayer-RTSP-Android安卓RTSP播放器低延遲播放延時優化策略 EasyPlayer-RTSP-Android播放器是一款專門針對RTSP協議進行過優化的流媒體播放器,其中我們引以為傲的兩個技術優勢就是起播速度快和播放延遲低。最近我們遇到一些需求,其對延遲要求

VideoView填入RTSP地址開啟後停了一會提示無法播放該視訊

VideoView 播放自己用DSS搭建的RTSP伺服器上的視訊,顯示無法開啟該視訊,但是別的伺服器上的資源可以正常播放,比如rtsp://218.204.223.237:554/live/1/66251FC11353

媒體技術學習筆記之(八)康、華IpCamera RTSP地址和格式

海康: rtsp://[username]:[password]@[ip]:[port]/[codec]/[channel]/[subtype]/av_stream 說明: username

瀏覽器播放rtsp媒體解決方案

wid 格式 script mar max-width main view pro tmp 老板提了一個需求,想讓網頁上播放景區監控的畫面,估計是想讓遊客達到未臨其地,已知其境的狀態吧。 說這個之前,還是先說一下什麽是rtsp協議吧。 RTSP(Real Time S

MAC下使用VLC搭建RTSP媒體服務器

pre 下載安裝 contents ide 播放 macos col inpu put 想在自己的mac上搭建一個RTSP流媒體服務器,找來找去,還是覺得VLC最簡單實用。 官網下載安裝vlc,安裝後路徑為:/Applications/VLC.app 實用命令啟動服務器,

媒體協議之RTSP客戶端的實現20171014

叠代 jrtplib 訪問 pac .cpp 服務端 blog 文件 僅支持 RtspClient是基於jrtplib實現的,目前僅支持h264格式,後續將不斷叠代優化,加入對其他格式的支持,並且將實現RTSP的服務端。 RtspClient的功能是接收服務端過來流,然後寫

go語言調用上下文拉起ffmpeg並引入livego的簡單媒體服務器

color 部分 bytes 流媒體 return ffmpeg tsp lang sed 想給項目組推一套視頻的播放方案,用於播放ip camera的的實時流,網上有很多人已經做過了,我這邊是使用golang,拉起上下文調用ffmpeg命令,獲取rtsp轉到livego的

一篇文章讀懂媒體傳輸協議RTP、RTCP、RTSP、SRTP&SRTCP

概要 一句話:RTSP發起/終結流媒體、RTP傳輸流媒體資料 、RTCP對RTP進行控制,同步。 因為CTC標準裡沒有對RTCP進行要求,因此在標準RTSP的程式碼中沒有看到相關的部分。而在私有RTSP的程式碼中,有關控制、同步等,是在RTP Header中做擴充套件定義實現

RTSP基礎之EasyDarwin媒體轉發環境搭建

這裡只是最基本EasyDarwin配置,Windows版本EasyDarwin,配置基本完成,下載地址:點這裡,下載完把EasyDarwin-Windows-x86_64解壓到windows中。 1.啟動EasyDarwin,執行EasyDarwin/start.bat啟動EasyDarwi

3518EV200 SDK中獲取和儲存H.264碼詳解

1 /****************************************** 2 step 2: Start to get streams of each channel. 3 ************************************