gstreamer avidemux增加h265支持

gstreamer avidemux增加h265支持

avi格式简介

AVI文件采用的是RIFF文件结构方式,RIFF(Resource Interchange File Format,资源互换文件格式)是微软公司定义的一种用户管理Windows环境中多媒体数据的文件格式,波形音频wave,MIDI和数字视频AVI都采用这种格式存储。RIFF文件的实际数据中,使用了列表(List)和块(Chunk)的形式来组织。列表可以嵌套列表和块。整个RIFF文件可以看成一个数据库,其数据块ID为RIFF ,称为RIFF块。一个RIFF文件中只允许存在一个RIFF块。RIFF块中包含一系列的子块,其中有一种子块的ID为“List”,称为LIST块,LIST块中可以再包含一系列的子块,但除了LIST块外的其他所有的子块都不能再包含子块。

块标识符ID为’RIFF’的chunk是比较特殊的,每一个RIFF文件首先存放的必须是一个RIFF chunk,并且只能有一个标识符为’RIFF’的chunk。RIFF chunk的数据域的起始位置是一个4字节的FormType(FourCC格式),用于标识RIFF chunk数据域中所包含的chunk的数据类型。紧接着FormType之后的数据域的内容则是RIFF chunk所包含的subchunk。

在这里插入图片描述

上图中的RIFF chunk包含有两个subchunk,可以看出RIFF chunk的数据域首先是4字节的FormType,接着是两个subchunk,每一个subchunk又包含有自己的标识符、数据域的大小以及数据域。 除了RIFF chunk可以嵌套其他的chunk外,另一个可以包含subchunk的就是LIST chunk,其示意图如下所示:

在这里插入图片描述

avi的文件头结构

在这里插入图片描述

ID为hdrl的LIST块,定义AVI文件的数据格式,hdrlLIST块包含两个子块,一个是ID为avih的子块和一个是ID为strl的LIST块。

  • avih块结构:用于记录AVI文件的全局信息,比如流的数量,视频图像的宽和高等,包含一个或多个strl子列表
  • 每个strl字列表至少包含一个strh块和一个strf

strh块结构:用于说明这个strlLIST块对应的数据流的头信息

strf块结构:strf子块紧跟在strh子块之后,其结构是strh子块的类型而定

  • 如果strh子块是视频数据流,则strf子块的内容是一个BITMAPINFO结构
  • 如果strh子块是音频数据流,则strf子块的内容是一个WAVEFORMAT结构
RIFF
- hdrl LIST
	- avih
	- strl
		- strh (vids)
		- strf 
		- JUNK
- info LIST
- JUNK (填充)
- movi LIST

实例分析gsreamer-1.16.3 avi解析h265

在gstreamer网站搜索avidemux,看到avidemux最新的版本支持很全,已经包含h265的caps,所以No decoder available for type 'video/x-avi-unknown,这个log大致判断是对codec识别错误导致:

https://gstreamer.freedesktop.org/documentation/

gst-launch播放命令:

 gst-launch-1.0 filesrc location=test.avi ! avidemux name=demux  demux.audio_00 ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_00 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink

avidemux sinkpad

gst-plugins-good/gst/avi/gstavidemux.c

avidemux的sink pad是caps为video/x-msvideo的类型:

static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("video/x-msvideo")
    );

sink pad的创建自然在gst_avi_demux_init中:

gst_avi_demux_init (GstAviDemux * avi)
{
  avi->sinkpad = gst_pad_new_from_static_template (&sink_templ, "sink");
  gst_pad_set_activate_function (avi->sinkpad,
      GST_DEBUG_FUNCPTR (gst_avi_demux_sink_activate));

hexdump可以看到文件头,和log中的输出一致:

$ hexdump -C hbc9_h265.avi | more
00000000  52 49 46 46 8e fc 73 00  41 56 49 20 4c 49 53 54  |RIFF..s.AVI LIST|
00000010  ca 22 00 00 68 64 72 6c  61 76 69 68 38 00 00 00  |."..hdrlavih8...|
00000020  56 82 00 00 00 00 00 00  00 00 00 00 10 09 00 00  |V...............|
00000030  48 19 00 00 00 00 00 00  02 00 00 00 00 00 10 00  |H...............|
00000040  c0 02 00 00 60 01 00 00  00 00 00 00 00 00 00 00  |....`...........|
00000050  00 00 00 00 00 00 00 00  4c 49 53 54 e0 10 00 00  |........LIST....|
00000060  73 74 72 6c 73 74 72 68  38 00 00 00 76 69 64 73  |strlstrh8...vids|
00000070  68 76 63 31 00 00 00 00  00 00 00 00 00 00 00 00  |hvc1............|
00000080  e9 03 00 00 30 75 00 00  00 00 00 00 48 19 00 00  |....0u......H...|
00000090  92 42 00 00 ff ff ff ff  00 00 00 00 00 00 00 00  |.B..............|
000000a0  c0 02 60 01 73 74 72 66  28 00 00 00 28 00 00 00  |..`.strf(...(...|
000000b0  c0 02 00 00 60 01 00 00  01 00 18 00 68 76 63 31  |....`.......hvc1|

行号为00000070: 68 76 63 31十六进制数就是0x31637668,对应的十进制是828601960

与log中输出的fourcc值一样,说明hvc1没有被正确识别:

avidemux gstavidemux.c:2390:gst_avi_demux_parse_stream:<avidemux0> caps=video/x-avi-unknown, fourcc=(int)828601960

在python中也可以将log中的这个值转成hex对比,前面hexdump中的第9行

>>> hex(828601960)
'0x31637668'

ubuntu播放

gst-launch-1.0 filesrc location=/home/hui/dload/h265.avi ! avidemux ! fakesink -v

ubuntu上升级到1.19.3播放正常,分析log输出,前面的判断正确,avi中的h265没有被识别,增加h265的支持,成功创建caps就可以了。

vids解析正常

    case GST_RIFF_FCC_vids:{
      guint32 fourcc;

      fourcc = (stream->strf.vids->compression) ?
          stream->strf.vids->compression : stream->strh->fcc_handler;
      caps = gst_riff_create_video_caps (fourcc, stream->strh,
          stream->strf.vids, stream->extradata, stream->initdata, &codec_name);

gst_riff_create_video_caps

从gstreamer高版本里面找到h265的部分patch加上就可以了:

$ cat 0001-riff-media-add-H.265.patch

From f98f8340140a2e6b8a7fb3c21823c348778ddff4 Mon Sep 17 00:00:00 2001
From: Nicola Murino <nicola.murino@gmail.com>
Date: Fri, 25 Jan 2019 22:48:17 +0100
Subject: [PATCH] riff-media: add H.265

Closes #359

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/43>
---
 gst-libs/gst/riff/riff-media.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/gst-libs/gst/riff/riff-media.c b/gst-libs/gst/riff/riff-media.c
index 6feda84a74..4bb723bf5b 100644
--- a/gst-libs/gst/riff/riff-media.c
+++ b/gst-libs/gst/riff/riff-media.c
@@ -353,6 +353,17 @@ gst_riff_create_video_caps (guint32 codec_fcc,
         *codec_name = g_strdup ("ITU H.264");
       break;
 
+    case GST_MAKE_FOURCC ('X', '2', '6', '5'):
+    case GST_MAKE_FOURCC ('x', '2', '6', '5'):
+    case GST_MAKE_FOURCC ('H', '2', '6', '5'):
+    case GST_MAKE_FOURCC ('h', '2', '6', '5'):
+    case GST_MAKE_FOURCC ('h', 'v', 'c', '1'):
+    case GST_MAKE_FOURCC ('H', 'V', 'C', '1'):
+      caps = gst_caps_new_empty_simple ("video/x-h265");
+      if (codec_name)
+        *codec_name = g_strdup ("H.265");
+      break;
+
     case GST_RIFF_VSSH:
       caps = gst_caps_new_simple ("video/x-h264",
           "variant", G_TYPE_STRING, "videosoft", NULL);
@@ -1887,6 +1898,7 @@ gst_riff_create_video_template_caps (void)
     GST_MAKE_FOURCC ('H', '2', '6', '3'),
     GST_MAKE_FOURCC ('V', 'X', '1', 'K'),
     GST_MAKE_FOURCC ('H', '2', '6', '4'),
+    GST_MAKE_FOURCC ('H', '2', '6', '5'),
     GST_MAKE_FOURCC ('H', 'F', 'Y', 'U'),
     GST_MAKE_FOURCC ('I', '2', '6', '3'),
     GST_MAKE_FOURCC ('I', '4', '2', '0'),
-- 
2.17.1

参考

RIFF文件格式详解

RIFFPad – RIFF File Viewer

avi格式解析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值