某簡單易懂的LibASS使用說明

前言

    最近在寫Foobar的彈幕支持插件(見 Foobar字幕(彈幕)支持插件開發日志),在ASS格式支持部分需要用到LibASS,這里就把使用的情況記錄一下吧~

簡介

    ASS / SSA格式,全稱Advanced Substation Alpha / Substation Alpha,是一種功能極為強大的字幕格式,其實跟ASS WE CAN是米有關系的~ASS本質是文本文檔,編輯非常方便.關于ASS格式的使用不是本文的討論范圍,這里不予敘述~

    LibASS則是一個輕量級的對ASS / SSA格式字幕進行渲染的函數庫.該庫使用C編寫,效率較高.據官方說明,LibASS和VSFilter兼容性最好~
    *LibASS依賴的第三方庫: FreeType, iConv(可選), FontConfig(可選)

    FreeType是LibASS使用的通用字體渲染庫,也是很強大的庫,作用是把系統的字庫(ClearType神馬的)渲染成單張Bitmap(位圖)~

使用流程

    以下就以LibASS自帶的Test.c為例,說明一下LibASS的工作方式.下列函數順序調用,即可最簡使用LibASS.

  1. 初始化LibASS / init()
    這個函數用于初始化LibASS的,只有兩個參數:輸出位圖的長和寬.
    1.ass_library_init()函數:
        作用:初始化LibASS的字幕庫(ASS_Library)
        參數:無
        返回值:字幕庫的指針/ ASS_Library*
    2.ass_renderer_init()函數:
        作用:初始化LibAss的渲染器(ASS_Renderer)
        參數:字幕庫的指針 / ASS_Library*
        返回值:渲染器的指針 / ASS_Renderer*
    3.ass_set_frame_size()函數:
        作用:指定輸出位圖大小
        參數1:渲染器的指針 / ASS_Render*
        參數2:輸出位圖的寬 / int
        參數3:輸出位圖的長 / int
        返回值:無
    4.ass_set_fonts()函數:
        作用:指定使用的字體庫,如果沒有使用FontConfig庫的話,必須指定字體,否則渲染失敗.
        參數1:渲染器的指針 / ASS_Renderer*
        參數2:字庫完整文件路徑 / const char*
        參數3:字體類型 / const char*
        參數4:是否使用FontConfig / int
        參數5:FontConfig路徑 / const char*
        參數6:是否更新FontConfig的緩沖 / int
        返回值:無
    ASS_Library結構體:
        字體信息庫.
    ASS_Renderer結構體:
        字幕渲染器,包含該幀的渲染信息.
  2. 讀取字幕
    初始化完成了就可以開始讀取ASS格式字幕了,LibASS很方便地把讀取文件寫在一個函數里面了,基本不用考慮文件編碼問題,因為這個函數已經為我們做好轉換的工作了.
    1.ass_read_file()函數:
        作用:讀取ASS格式字幕到音軌庫(ASS_Track)
        參數1:字幕庫的指針 / ASS_Library*
        參數2:ASS字幕文件完整路徑 / char*
        參數3:代碼頁 / char* (如果ASS文件不是Unicode編碼的話,需要手動檢測ANSI的代碼頁)
        返回值:音軌庫的指針 / ASS_Track*
    ASS_Track結構體:
        與其叫音軌庫,我覺得叫字幕事件庫更合適,包含一個曲目的字幕事件.
  3. 渲染字幕
        萬事具備,在上面函數調用完后,LibASS有足夠的信息去渲染字幕了.
    1.ass_render_frame()函數:
        作用:生成某幀的字符位圖庫(ASS_Image).
        參數1:渲染器的指針 / ASS_Renderer*
        參數2:音軌庫的指針 / ASS_Track*
        參數3:需要渲染幀的時間(單位:毫秒) / long long
        參數4:檢測前后兩幀是否相同的標識 / int*
        返回值:當前幀的字符位圖庫的指針 / ASS_Image*
        *注意這個函數,每次調用會把上一次生成的ASS_Image釋放
    2.gen_image()函數:
        這個函數其實不是LibASS的函數,是test.c的函數例子.
        作用:生成一張自定義大小的空自定義位圖(image_t),且為其分配內存空間.
        參數1:輸出位圖的寬 / int
        參數2:輸出位圖的長 / int
        返回值:自定義位圖的指針 / image_t*
    3.blend()函數:
        這個函數也不是LibASS的函數,且循環調用blend_single()函數.
        作用:把參數2中字符位圖庫的位圖混合到參數1的自定義位圖中.
        參數1:自定義位圖的指針 / image_t*
        參數2:字符位圖庫的指針 / ASS_Image*
        返回值:無
  4. 清理工作
        至此,已經完成對1幀字幕的渲染,得到了一幅自定義格式的位圖了.如果不需要再渲染其他幀,則需要對LibASS進行清理.
    1.ass_free_track()函數:
        參數:音軌庫的指針 / ASS_Track*
    2.ass_renderer_done()函數:
        參數:渲染器的指針 / ASS_Renderer*
    3.ass_library_done()函數:
        參數:字幕庫的指針 / ASS_Library*

    至此完成對LibASS的使用,生成的位圖(Bitmap)可以按照自己需要再加工成別的圖片格式,詳情可以查看其他開源圖片格式的開發文檔,這里不再敘述.
    需要特別注意的是,如果要獲得可以直接讓視頻接口支持的位圖,還需要自行了解接口的SDK說明~

Remark

這里說明一下使用LibASS要注意的地方.

  1. 關于ASS_Image的數據結構
    結構體定義:
        w:字符位圖的寬 / int
        h:字符位圖的長 / int
        stride:字符位圖的塊大小 / int
        bitmap:字符位圖的數據 / unsigned char*
        color:字符位圖的顏色 / unsigned
        dst_x:字符位圖在自定義位圖的x坐標 / int
        dst_y:字符位圖在自定義位圖的y坐標 / int
        next:下一張字符位圖的指針 / ASS_Image*
    說明:
    Stride是一幅位圖的塊大小,在很多情況都需要用到,計算公式如下:
        Stride = 每像素字節數 * 位圖寬度
    ASS_Image定義的是單色位圖,故每像素字節數為1,則這里Stride = 位圖寬度.可得Bitmap的總Buffer Size:
        Size = Stride * 位圖高度,代入上式:
        Size = 位圖寬度 * 位圖高度 (單位:Byte)
    在這里,Bitmap的數據用于表示每像素的灰度(或Alpha值).
  2. 關于image_t的數據結構
    結構體定義
        width:輸出位圖的長 / int
        height:輸出位圖的寬 / int
        stride:位圖塊大小 / int
        buffer:位圖數據 / unsigned char*
    說明:
    這個結構體并不是LibASS的數據結構,是test.c的自定義位圖格式.
    這里的Stride依照需求,取值會不同,公式仍然和上一樣.如果要獲得標準RGB(24Bit / 3Byte)位圖,則這里的位圖塊大小:
        Stride = 3 * 位圖寬度
    如果想要獲得ARGB(32Bit / 4Byte)的位圖的話,則位圖塊大小:
        Stride = 4 * 位圖寬度
    總位圖Buffer Size計算方式同上.
  3. 關于位圖數據(Bitmap Buffer)的數據結構
    按照標準Windows Bitmap定義,(24bit / 32bit)位圖每像素信息儲存方式:
    0xBBGGRR(AA)
    如果是2Bit – 16Bit的位圖,儲存將按照顏色表(Color Pattern)方式存儲,這里不在討論.

后記

    LibASS一直作為視頻播放器內部使用的開源庫,以其輕便高效的特點,完全沒有壓力地占領了大部分視頻播放器對ASS / SSA的支持方式.
雖然官方沒有給出完成的SDK文檔,但是我覺得源代碼 / 頭文件給出的注釋已經很給力了,我寫這篇東西貌似有點多此一舉?!

  1. 暫無評論

  1. 暫無 Trackback

?

return top

捕鱼王小游戏 天津十一选五跨度 维护彩票网站 蛙出门会赚钱吗 福辽宁35选7开奖结果彩票控 11月8日七星彩走势图 体彩7星彩开奖结果查询 95彩票群 app测试之家赚钱是真的吗 广西快乐十分钟走势图 组选奖号042