最簡單的iOS 推流程式碼,視訊捕獲,軟編碼(faac,x264),硬編碼(aac,h264),美顏,flv編碼,rtmp協議,陸續更新程式碼解析,你想學的知識這裡都有,願意懂直播技術的同學快來看!!
原始碼:https://github.com/hardman/AWLive
rtmp(一般大寫,小寫會被認為英文不好或不專業,iOS開發者對這一點更為敏感)協議是Adobe公司為Flash視訊的實時傳輸開發的一個開放協議。
本文不探究rtmp協議的原理,只是從程式碼角度來看,客戶端如何使用librtmp完成推流功能。
#librtmp 專案內使用的librtmp是使用rtmpdump編譯的。如果遇到程式碼上的疑問可以通過閱讀rtmpdump的原始碼尋找答案。
#程式碼解析 ##外部介面 rtmp相關程式碼在aw_rtmp.c和aw_rtmp.h中。 對外介面包含一個context和3個函式:
//aw_rtmp_context是一個context,用於儲存一些外部傳入及內部共享的變數。
//寫成context統一管理,否則就要寫很多全域性變數了。
typedef struct aw_rtmp_context{
//rtmp url
char rtmp_url[256];
//librtmp 中的結構體,作為RTMP連線上下文
RTMP *rtmp;
...
...
//外部狀態檢測
//狀態變化回撥,注意,不要在狀態回撥中做釋放aw_rtmp_context的操作。
//如果非要釋放,請延遲一幀。
aw_rtmp_state_changed_cb state_changed_cb;
//當前狀態
aw_rtmp_state rtmp_state;
} aw_rtmp_context;
//開啟rtmp
extern int aw_rtmp_open(aw_rtmp_context *ctx);
//寫入資料
extern int aw_rtmp_write(aw_rtmp_context *ctx, const char *buf, int size);
//關閉rtmp
extern int aw_rtmp_close(aw_rtmp_context *ctx);
複製程式碼
3個主要函式分別是:開啟,寫入資料,關閉。 除此之外,對於外部呼叫者來說,最重要的是要監聽rtmp連線的各種狀態來調整上層邏輯。 而狀態回撥就在 aw_rtmp_context中。
專案中,初始化 & 關閉rtmp的程式碼在 aw_streamer.c 中
//初始化rtmp連線
static int8_t aw_steamer_open_rtmp_context(){
//建立context 傳入rtmpurl及狀態回撥
if (!s_rtmp_ctx) {
s_rtmp_ctx = alloc_aw_rtmp_context(s_rtmp_url, aw_streamer_rtmp_state_changed_callback);
}
//open
return aw_rtmp_open(s_rtmp_ctx);
}
//關閉rtmp連線
static void aw_streamer_close_rtmp_context(){
if (s_rtmp_ctx) {
aw_rtmp_close(s_rtmp_ctx);
}
aw_log("[d] closed rtmp context");
}
複製程式碼
傳送資料的程式碼在aw_streamer.c中:
static void aw_streamer_send_flv_tag_to_rtmp(aw_flv_common_tag *common_tag){
... ...
aw_rtmp_write(s_rtmp_ctx, (const char *)s_output_buf->data, s_output_buf->size);
... ...
}
複製程式碼
##開啟rtmp
//開啟rtmp,都是固定套路。
int aw_rtmp_open(aw_rtmp_context *ctx){
...
...
//初始化
ctx->rtmp = RTMP_Alloc();
RTMP_Init(ctx->rtmp);
//連線超時
ctx->rtmp->Link.timeout = 1;
//設定url
if (!RTMP_SetupURL(ctx->rtmp, ctx->rtmp_url)) {
AWLog("[error ] aw rtmp setup url = %s\n", ctx->rtmp_url);
recode = -2;
goto FAILED;
}
//可寫
RTMP_EnableWrite(ctx->rtmp);
//buffer長度
RTMP_SetBufferMS(ctx->rtmp, 0);
//開始連線
if (!RTMP_Connect(ctx->rtmp, NULL)) {
recode = -3;
goto FAILED;
}
//連線
if (!RTMP_ConnectStream(ctx->rtmp, 0)) {
recode = -4;
goto FAILED;
}
return 1;
FAILED:
//若中間環節出錯,斷開連線
aw_rtmp_close(ctx);
return !recode;
}
複製程式碼
##rtmp寫入(傳送)資料
int aw_rtmp_write(aw_rtmp_context *ctx, const char *buf, int size){
... ...
//RTMP_Write內部有時會排出SIGPIPE訊號,在這裡處理一下
signal(SIGPIPE, SIG_IGN);
int write_ret = RTMP_Write(ctx->rtmp, buf, size);
... ...
return write_ret;
}
複製程式碼
rtmp關閉
int aw_rtmp_close(aw_rtmp_context *ctx){
... ...
//主要這兩句
RTMP_Close(ctx->rtmp);
RTMP_Free(ctx->rtmp);
... ...
return 1;
}
複製程式碼
librtmp庫使用方法介紹完畢。
文章列表
- 1小時學會:最簡單的iOS直播推流(一)專案介紹
- 1小時學會:最簡單的iOS直播推流(二)程式碼架構概述
- 1小時學會:最簡單的iOS直播推流(三)使用系統介面捕獲音視訊
- 1小時學會:最簡單的iOS直播推流(四)如何使用GPUImage,如何美顏
- 1小時學會:最簡單的iOS直播推流(五)yuv、pcm資料的介紹和獲取
- 1小時學會:最簡單的iOS直播推流(六)h264、aac、flv介紹
- 1小時學會:最簡單的iOS直播推流(七)h264/aac 硬編碼
- 1小時學會:最簡單的iOS直播推流(八)h264/aac 軟編碼
- 1小時學會:最簡單的iOS直播推流(九)flv 編碼與音視訊時間戳同步
- 1小時學會:最簡單的iOS直播推流(十)librtmp使用介紹
- 1小時學會:最簡單的iOS直播推流(十一)sps&pps和AudioSpecificConfig介紹(完結)