天天看點

hls直播實作源碼V2(h264,aac流輸入,ffmpeg實作,MFC,VC環境,ts,m3u8)

周星馳來也!

hls直播實作源碼V2(h264,aac流輸入,ffmpeg實作,MFC,VC環境,ts,m3u8)

像很多80,90後年輕人(老男人吧)一樣,周星馳一直就是哥喜愛的電影演員之一,不僅喜歡星爺的人物形象,更是喜歡這種樂觀向上的精神!(哥16年的QQ一直就是周星馳這個昵稱)。

轉入主題吧:

本文demo下載下傳位址http://download.csdn.net/download/xjb2006/10119982

hls直播實作源碼V2(h264,aac流輸入,ffmpeg實作,MFC,VC環境,ts,m3u8)

在QQ技術群裡,很多人都在研究ffmpeg,因為功能強大,簡單直接就能實作想要的功能,但是想要用好,還是要下一些功夫。

今天的主題就是怎樣實作對h264,aac流輸入,合成後輸出ts,m3u8,即HLS,蘋果裝置的點播方案!!!!!!!!!!!!!!!!!!!!

網上有很多關于檔案轉mp4或者其他檔案格式的例子,但是換成資料流輸入了,怎麼辦呢?很多人也是一籌莫展。網上也鮮有這種代碼或者文章。

今天,哥哥就順便說幾句,關于我自己的一些想法。

晚上有很多例子是關于輸入視訊檔案的,對我們有些參考,但是要換成輸入h264或者aac資料流,大家都是沒辦法啊。

1、HLS是什麼?

HLS (HTTP Live Streaming)是Apple的動态碼率自适應技術(複制過來的),隻有蘋果的浏覽器才能直接用,因為蘋果不支援flash控件(自然也不支援rtmp),是以才有了HLS技術用于點播直播。調試的時候可以下載下傳一個VLC播放器,這個播放器可以打開m3u8。

2、TS檔案

百度這樣說的:“ts是高清錄影機拍攝下進行的封裝格式,全稱為MPEG2-TS。ts即"Transport Stream"的縮寫。MPEG2-TS格式的特點就是要求從視訊流的任一片段開始都是可以獨立解碼的。先不管這些了,反正HLS就要用到TS格式的檔案,一個一個的。貼張圖吧,百說不如一見:

hls直播實作源碼V2(h264,aac流輸入,ffmpeg實作,MFC,VC環境,ts,m3u8)

3、m3u8檔案

M3U8檔案是指UTF-8編碼格式的M3U檔案。M3U檔案是記錄了一個索引純文字檔案,打開它時播放軟體并不是播放它,而是根據它的索引找到對應的音視訊檔案的網絡位址進行線上播放。

M3U8檔案舉例,例如使用雲圖TV點播直播節目時,發送請求:

http://121.199.63.236:7613/m3u8/cckw1/szws.m3u8?

看到沒,其實蘋果的點播就是http上直接通路。

4、實作過程和思路:

設定存ts,m3u8的路徑,輸入h264和aac流,根據設定的ts長度和個數,不斷更新ts檔案和m3u8檔案

說了這麼多基礎,來點實際的吧:

我封裝的最後的接口函數:

void StartHLS(CString szPath,CString szName="xiao");//開始啟動hls,路徑為儲存m3u8和ts的路徑

void SetAudioProperty(int channels, int samplerate, int bitspersample);

void SetVideoProperty(int width, int height, double framerate);

void StopHLS(void);

void H264In(BYTE* pH264, LONG nH264Len, LONG nTimeStamp=0);

void AACIn(BYTE* pAAC, LONG nAACLen, LONG nTimeStamp=0);

調用ffmpeg的步驟:

av_register_all();

定義幾個全局的:

AVFormatContext* output_format_context;//輸出檔案結構上下文

     AVStream* o_video_stream ;

     AVStream *o_audio_stream ;

輸入h264關鍵幀:

通過關鍵幀擷取視訊資訊并

avio_alloc_context(這個函數很多文章或者代碼裡面都沒有提到過吧),生成一個自定義輸入io,用來探測h264的格式

//讀入資料avformat_open_input

//設定輸入結構體資訊

avformat_find_stream_info

//設定輸出檔案格式資訊

avformat_alloc_output_context2

//打開輸出檔案

avio_open

//添加音視訊流

avformat_new_stream

//寫入頭

av_dump_format、avformat_write_header

至此,檔案初始化工作完成

接下來寫資料啦

av_packet_from_data、av_packet_rescale_ts、av_interleaved_write_frame、av_write_trailer

最後記得釋放

avio_close、avformat_free_context

完了,搞完收工!!!!!!看看效果

hls直播實作源碼V2(h264,aac流輸入,ffmpeg實作,MFC,VC環境,ts,m3u8)

中間有很多困擾:枚舉下:比如ts檔案格式必須輸入的aac為 ADTS編碼的,即有7個位元組的頭,沒有就别想播放。

音視訊同步,主要還是通過音視訊時間戳pts,dts同步的。m3u8及ts檔案更新,根據設定的一個ts檔案秒數和個數進行不斷更新,比如設定的5秒一個,一共3個,那麼,每隔3秒,儲存ts并建立新的ts,然後更新m3u8檔案資訊.

我的m3u8檔案内容:

#EXTM3U

#EXT-X-TARGETDURATION:10

#EXT-X-MEDIA-SEQUENCE:103

#EXTINF:10,

xiao-103.ts

#EXTINF:10,

xiao-104.ts

#EXTINF:10,

xiao-105.ts

測試的時候,裝備一台蘋果手機(腎沒了沒辦法就下載下傳個VLC播放器也行),一個免費的http伺服器軟體,我下的免費的easywebserver。準備h264資料源和AAC資料源,這方面辦法很多,讀h264,aac檔案,截取螢幕或者攝像頭,aac擷取麥克風轉成AAC,或者輸入音頻檔案轉成AAC(編碼一定要有 ADTS 頭啊,切記切記)

但是上面說了這麼多,應該也能自己做了吧。什麼時候傳個DEMO上來,有空再說吧

傳點代碼(關鍵的一段):

[cpp]  view plain  copy

[cpp]  view plain  copy

  1. void CHLSSend::H264In(BYTE* pH264, LONG nH264Len, LONG nTimeStamp)  
  2. {  
  3.     MP4ENC_NaluUnit nalu;  
  4.     int pos = 0, len = 0;  
  5.     bool bKeyFrame=false;  
  6.     while (len = ReadOneNaluFromBuf((const unsigned char *)pH264,nH264Len,pos,nalu))  
  7.     {  
  8.         if(nalu.type==0x05)  
  9.         {  
  10.             bKeyFrame=true;  
  11.             break;  
  12.         }  
  13.         pos += len;  
  14.     }  
  15.     if(bKeyFrame)  
  16.     {  
  17.         try  
  18.         {  
  19.             s_write_file_head(pH264, nH264Len);  
  20.         }  
  21.         catch(...)  
  22.         {  
  23.             TRACE("寫入檔案頭異常!\n");  
  24.             isfirst=true;  
  25.             return;  
  26.         }  
  27.     }  
  28.     if (isfirst)  
  29.         return;  
  30.     if(nTimeStamp==0)  
  31.         nTimeStamp=::GetTickCount();  
  32.     if(m_bFirstVideo)  
  33.     {  
  34.         m_uFirstVideo=nTimeStamp;  
  35.         m_u64VideoPTS = nTimeStamp;  
  36.         m_bFirstVideo=false;  
  37.     }  
  38.     AVPacket pkt;  
  39.     av_init_packet(&pkt);  
  40.     uint8_t* avdata = (uint8_t*)av_malloc(nH264Len + AV_INPUT_BUFFER_PADDING_SIZE);  
  41.     memcpy(avdata, pH264, nH264Len);  
  42.     //   
  43.     int iiiii = av_packet_from_data(&pkt, (uint8_t*)avdata, nH264Len);  
  44.     if (iiiii == 0)  
  45.     {  
  46.         Lock.Lock();  
  47.         int pts=PTS2TIME_SCALE(nTimeStamp, m_uFirstVideo, m_fps);  
  48.         //TRACE("視訊時間:%0.2f  視訊時間2: %d\n",(double)pts*1000/(double)m_fps,(m_nVideoCount));  
  49.         pkt.pts = (m_nVideoCount++);//音頻幀率=48000/1024  視訊幀率:30=30*1024/1024    
  50.         pkt.dts = pkt.pts;  
  51.         av_packet_rescale_ts(&pkt, o_video_stream->codec->time_base, o_video_stream->time_base);  
  52.         pkt.stream_index = o_video_stream->index;  
  53.         pkt.duration = 1;  
  54.         pkt.pos = -1;  
  55.         if(bKeyFrame)  
  56.             pkt.flags |= AV_PKT_FLAG_KEY;  
  57.         int result = av_interleaved_write_frame(output_format_context, &pkt);     
  58.         if(result!=0)  
  59.         {  
  60.             printf("fail2\n");  
  61.             //MessageBox(0,"111",0,MB_OK);  
  62.         }  
  63.         //判斷一個TS是否完成  
  64.         m_nOneTsTime=GetVideoTime(m_nVideoCount);  
  65.         int current_segment_duration = (int)(m_nOneTsTime-m_nFirstTime + 0.5);  
  66.         //actual_segment_durations[last_segment] = (current_segment_duration > 0 ? current_segment_duration: 1);  
  67.         if(m_nOneTsTime-m_nFirstTime>=ONETSLEN)//  
  68.         {  
  69.             StopWriteAndNewTs();  
  70.             m_nFirstTime=m_nOneTsTime;//第一次檔案寫入時間  
  71.             TRACE("10秒到,寫入檔案并建立新檔案\n");  
  72.         }  
  73.         Lock.Unlock();  
  74.     }  
  75.     else  
  76.     {  
  77.         printf("fail\n");  
  78.         //MessageBox(0,"222",0,MB_OK);  
  79.     }  
  80.     av_free_packet(&pkt);//他會把buff清理掉  
  81. }  

今天花了2個小時把DEMO做好了,可以下載下傳看看效果,有問題或者需要交流,可以聯系我,謝謝(前面一個是v2版本,後面是v1版本)

http://download.csdn.net/download/xjb2006/10119982

http://download.csdn.net/download/xjb2006/10106146

hls直播實作源碼V2(h264,aac流輸入,ffmpeg實作,MFC,VC環境,ts,m3u8)

*需要合作的聯系QQ35744025,可以當當技術顧問或者核心技術提供,本人03年從事工作,“精通”音視訊應用程式設計技術(勉強加個精通,吸引眼球,哈哈),精通VC,MFC,多媒體教學軟體,錄播軟體,直播軟體的核心技術大部分已掌握,如ffmpeg技術,Directshow技術,MP4,FLV編碼合成,H264,AAC,MP3,可以運用IPP進行高效圖像空間轉換等,可以運用INTEL和cuda進行硬體H264編解碼,可以實作240幀1080P實時編碼,完全同步及平滑度極高,rtmp,HLS直播推送,rtmp伺服器,YV12,YUV422,NV12,RGB24,RGB32熟悉轉換,縮放,wav,AAC, mp3的編碼解碼,視訊切換特效算法,視訊水印,LOGO,文字。螢幕截取錄像,攝像頭捕獲錄像,D3D高效視訊圖像顯示,OPENCV,圖像庫ximage,GDI,GDIPLUS熟練應用,語音識别及文字轉換,人臉識别及比對,區域網路内遠端控制,音視訊實時通話,聲霸卡捕獲回放等,另外SQL資料庫,ACCESS,EXCEL資料庫,DOC,PDF檔案打開提取,FTPServer,Client,以上所有代碼均已商用。