1小時學會:最簡單的iOS直播推流(十)librtmp使用介紹

hard_man發表於2018-01-19

最簡單的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. 1小時學會:最簡單的iOS直播推流(一)專案介紹
  2. 1小時學會:最簡單的iOS直播推流(二)程式碼架構概述
  3. 1小時學會:最簡單的iOS直播推流(三)使用系統介面捕獲音視訊
  4. 1小時學會:最簡單的iOS直播推流(四)如何使用GPUImage,如何美顏
  5. 1小時學會:最簡單的iOS直播推流(五)yuv、pcm資料的介紹和獲取
  6. 1小時學會:最簡單的iOS直播推流(六)h264、aac、flv介紹
  7. 1小時學會:最簡單的iOS直播推流(七)h264/aac 硬編碼
  8. 1小時學會:最簡單的iOS直播推流(八)h264/aac 軟編碼
  9. 1小時學會:最簡單的iOS直播推流(九)flv 編碼與音視訊時間戳同步
  10. 1小時學會:最簡單的iOS直播推流(十)librtmp使用介紹
  11. 1小時學會:最簡單的iOS直播推流(十一)sps&pps和AudioSpecificConfig介紹(完結)

相關文章