2014-01-15 74 views
3

最近我正在編寫提供H.264流的IP攝像機的客戶端。我現在使用FFmpeg 2.1.1來解碼相機提供的流。使用FFmpeg無法解碼H.264流(Annex.B)

這裏的應用程序的一些代碼:

初始化:

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); 
    } 

解碼:

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 
     } 
    } 

通過上面的代碼,我可以得到一些輸出,如:

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關鍵幀的切片,並將下列NAL單元形成正常的幀。

而且avcodec_decode_video2功能不會產生任何錯誤,只是回頭率1和gotPicture常是0

如果我清除AVCodecContext.flags2,它開始抱怨我提供的包不包含框架:

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到流複用器,以MP4容器,並可以與任何播放器上播放的MP4文件。

我接收到的原始數據是一樣的東西:

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... 
... 

回答

0

我創建的libavcodec的調試版本,並做了一些調試。我發現我使用的是AVPacket結構的ealier版本,所以傳遞給解碼器的數據格式不正確。我根據頭文件編寫了一個新版本的AVPacket,現在它就像一個魅力一樣。