首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不能使用FFmpeg解码H.264流(附件B)

不能使用FFmpeg解码H.264流(附件B)
EN

Stack Overflow用户
提问于 2014-01-15 12:02:03
回答 1查看 3.1K关注 0票数 3

最近,我正在编写一个提供H.264流的IP摄像头的客户端。我现在使用FFmpeg 2.1.1来解码摄像机提供的流。

下面是应用程序的一些代码:

初始化:

代码语言:javascript
复制
    private unsafe void InitFFmpeg()
    {
        FFmpeg.avcodec_register_all();
        var codec = FFmpeg.avcodec_find_decoder(AVCodecID.AV_CODEC_ID_H264);
        avcodec = (IntPtr)codec;

        var ctx=FFmpeg.avcodec_alloc_context3(avcodec);
        avcontext = (IntPtr)ctx;

        ctx->codec = avcodec;
        ctx->pix_fmt = AVPixelFormat.PIX_FMT_YUV420P;
        ctx->flags2 |= 0x00008000;//CODEC_FLAG2_CHUNKS

        var options = IntPtr.Zero;
        int result = FFmpeg.avcodec_open2(avcontext, avcodec, ref options);
        avframe = FFmpeg.av_frame_alloc();
        avparser = FFmpeg.av_parser_init(AVCodecID.AV_CODEC_ID_H264);
        FFmpeg.av_init_packet(ref avpacket);
        inBuffer = Marshal.AllocHGlobal(300 * 1024);
    }

解码:

代码语言:javascript
复制
    private void Decode(byte[] data, int size)
    {
        IntPtr pOut = IntPtr.Zero;
        int outLen = 0;

        Marshal.Copy(data, 0, inBuffer, size);

        int gotPicture = 0;

        var rs = FFmpeg.av_parser_parse2(avparser, avcontext, ref pOut, ref outLen, inBuffer, size, 0, 0, 0);
        if (outLen <= 0 || pOut.ToInt32() <= 0)
        {
            //no enough data to construct a frame, return and receive next NAL unit.
            return;
        }
        avpacket.data = pOut;
        avpacket.size = outLen;
        avpacket.flags |= PacketFlags.Key;
        var len = FFmpeg.avcodec_decode_video2(avcontext, avframe, ref gotPicture, ref avpacket);
        Console.WriteLine("avcodec_decode_video2 returned " + len);
        if (gotPicture != 0)
        {
            //some YUV to RGB stuff
        }
    }

使用上面的代码,我可以得到如下的一些输出:

代码语言:javascript
复制
NAL unit 1: resolution=1280x720, key-frame=True, size=26.
NAL unit 2: resolution=1280x720, key-frame=False, size=8.
NAL unit 3: resolution=1280x720, key-frame=False, size=97222.
NAL unit 4: resolution=1280x720, key-frame=False, size=14129.
avcodec_decode_video2 returned 1
NAL unit 5: resolution=1280x720, key-frame=False, size=12522.
NAL unit 6: resolution=1280x720, key-frame=False, size=12352.
avcodec_decode_video2 returned 1
NAL unit 7: resolution=1280x720, key-frame=False, size=12291.
NAL unit 8: resolution=1280x720, key-frame=False, size=12182.

从输出中,我可以看到解析器可以识别摄像机发送的NAL单元,并可以从它们构造帧。

NAL单元1至4是包含SPS/PPS的关键帧的切片,以下2个NAL单元构成正常帧。

avcodec_decode_video2函数不会产生任何错误,但是只会继续返回1,而gotPicture总是0。

如果我清除了AVCodecContext.flags2,它就会开始抱怨我提供的数据包没有包含任何帧:

代码语言:javascript
复制
NAL unit 100: resolution=1280x720, frame-rate=0, key-frame=True, size=26.
NAL unit 101: resolution=1280x720, frame-rate=0, key-frame=False, size=8.
NAL unit 102: resolution=1280x720, frame-rate=0, key-frame=False, size=96927.
NAL unit 103: resolution=1280x720, frame-rate=0, key-frame=False, size=17149.
[h264 @ 01423440] no frame!
avcodec_decode_video2 returned -1094995529
NAL unit 104: resolution=1280x720, frame-rate=0, key-frame=False, size=12636.
NAL unit 105: resolution=1280x720, frame-rate=0, key-frame=False, size=12338.
[h264 @ 01423440] no frame!

如果将原始流写入文件,则可以使用FFmpeg将流mux到mp4容器,并可以与任何播放器一起播放mp4文件。

我收到的原始数据如下:

代码语言:javascript
复制
00 00 00 01 67 42 00 28 E9 00 A0 0B 75 C4 80 03 6E E8 00 CD FE 60 0D 88 10 94
00 00 00 01 68 CE 31 52
00 00 00 01 65 88 81 00 06 66 36 25 11 21 2C 04 3B 81 E1 80 00 85 4B 23 9F 71...
...
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-01-16 10:59:07

我创建了libavcodec的调试构建并进行了一些调试。我发现我使用的是AVPacket结构的一个更实用的版本,所以传递给解码器的数据是错误的。我根据头文件编写了一个新版本的AVPacket,现在它工作起来很有魅力。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21136913

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档