6

I am receiving a h264 stream where I at least know the size of one frame. The stream is coming in right as I can store it in a file and playback with vlc. Playing back a file is no problem for me as I include the libavformat. But libavformat gives me back an AVPacket which I can directly give to avcodec_decode_video2. In this case I got a bytestream. How can I give the raw h264 stream to the avcodec_decode_video2? How can I wrap my data into a AVPacket. VLC does not need to guess any data.

Martin Schlott
  • 4,369
  • 3
  • 25
  • 49

1 Answers1

7

It is more or less easy to decode a stream. This code is working perfect for me:

class ffmpegstreamdestination
{
public:
    ffmpegstreamdestination(AVCodecID decoder): 
    {       
        m_pCodec= avcodec_find_decoder(decoder);
        m_pCodecCtx = avcodec_alloc_context3(m_pCodec);
        avcodec_open2(m_pCodecCtx,m_pCodec,0);
        m_pFrame=avcodec_alloc_frame();
    }

    ~ffmpegstreamdestination()
    {
        av_free(m_pFrame);
        avcodec_close(m_pCodecCtx);
    }

    void decodeStreamData(unsigned char * pData, size_t sz)
    {
        AVPacket        packet;
        av_init_packet(&packet);

        packet.data=pData;
        packet.size=(int)sz;
        int framefinished=0;
        int nres=avcodec_decode_video2(m_pCodecCtx,m_pFrame,&framefinished,&packet);

        if(framefinished)
        {
                   // do the yuv magic and call a consumer
        }

        return;
    }

protected:
    AVCodecContext  *m_pCodecCtx;
    AVCodec         *m_pCodec;
    AVFrame         *m_pFrame;
};

the call decodeStreamData expect the data as frames. You have to search your stream for the NAL (more or less a header magic number) which is in h264 case 0x00000001 .Its the beginning of a frame. Filling the AVPacket is not as problematic as I thought. If you do not have the information, you can left the attributes in it as the are init by av_init_packet. There are only problems if you have a different framerate for example.

As always, if you see a bug or think something would work otherwise better, a short message would be welcome.

Martin Schlott
  • 4,369
  • 3
  • 25
  • 49
  • hi, how can i parse `0x00000001`, because this start codes repeats before `SPS` and `PPS`? – nmxprime Feb 12 '14 at 10:17
  • @nmxprime it is better to start a new question about that. As far as I know, you can simply iterate through pData like: for(size_t i=0;i – Martin Schlott Feb 12 '14 at 14:06
  • i tried like this, but i may be iterating wrongly, so not succeeded ! Let me try!!Actually, Typically the file contains data for 100 frames,which means 100's of`(sps,pps and data)`. The same start code is used for sps,pps and data. BTW, what boundary checking you're telling of? – nmxprime Feb 12 '14 at 14:40
  • @nmxprime our question is going to far to response it in the comment section. Open a new question with your code. Add a comment here to your question and I + 1 million coders will look into your problem :-) – Martin Schlott Feb 12 '14 at 15:13
  • I have raw data from RTSP stream. Getting this error "[h264 @ 001436e0] no frame!", "nres" value is always less than 0. Any hing whats wrong with my code? – Tariq Mar 24 '15 at 10:59
  • @Tariq Post a new question with an example code. Your problem may be the streamdata itself, not the decoding. – Martin Schlott Mar 24 '15 at 21:23
  • avcodec_decode_video2 is deprecated, use avcodec_send_packet instead. Source: Documentation in https://github.com/FFmpeg/FFmpeg/blob/master/libavcodec/avcodec.h – Eyal D Nov 28 '19 at 07:59