0

I have encoded some frames using x264, using x264_encoder_encode and after that I have created AVPackets using a function like this:

bool PacketizeNals( uint8_t* a_pNalBuffer, int a_nNalBufferSize, AVPacket* a_pPacket )
{
    if ( !a_pPacket )
return false;
    a_pPacket->data = a_pNalBuffer;
    a_pPacket->size = a_nNalBufferSize;
    a_pPacket->stream_index = 0;
    a_pPacket->flags = AV_PKT_FLAG_KEY;

    a_pPacket->pts = int64_t(0x8000000000000000);
    a_pPacket->dts = int64_t(0x8000000000000000);
}

I call this function like this:

x264_nal_t* nals;
int num_nals = encode_frame(pic, &nals);
for (int i = 0; i < num_nals; i++)
{
    AVPacket* pPacket = ( AVPacket* )av_malloc( sizeof( AVPacket ) );
    av_init_packet( pPacket );
    if ( PacketizeNals( nals[i].p_payload, nals[i].i_payload, pPacket ) )
    {
        packets.push_back( pPacket );
    }
}

Now what I want to do is to decode these AVPackets using avcodec_decode_video2. I think the problem is that I haven't initialized properly the decoder because to encode I used "ultrafast" profile and "zerolatency" tune ( x264 ) and to decode I don't know how to specify to ffmpeg these options. In some examples I have read people initialize the decoder using the file where the video is stored, but in this case I have directly the AVPackets. What I'm doing to try to decode is:

avcodec_init();  
avcodec_register_all();  
AVCodec* pCodec;  
pCodec=avcodec_find_decoder(CODEC_ID_H264);  
AVCodecContext* pCodecContext;  
pCodecContext=avcodec_alloc_context();  
avcodec_open(pCodecContext,pCodec);  
pCodecContext->width = 320;
pCodecContext->height = 200;
pCodecContext->extradata = NULL;
unsigned int nNumPackets = packets.size();
int frameFinished = 0;
for ( auto it = packets.begin(); it != packets.end(); it++ )
{
    AVFrame* pFrame;
    pFrame = avcodec_alloc_frame();
    AVPacket* pPacket = *it;
    int iReturn = avcodec_decode_video2( pCodecContext, pFrame, &frameFinished, pPacket );
}

But in iReturn always is -1.

Can anyone help me? Sorry if my knowledge in this area es low, I'm new.

Thanks.

Raul Calvo
  • 11
  • 3
  • 7

3 Answers3

2

I have written a simple client/server application that streams raw RGB video using lib x264 for encoding and ffmpeg for decoding. You can find the code here: https://github.com/filippobrizzi/raw_rgb_straming

It shows how to setup x264 and ffmpeg to encode/decode.

filippo
  • 146
  • 1
  • 7
1

Right now you initialize the decoder like

pCodecContext->extradata = NULL;

this is not correct. You need to allocate a memory for this field and copy data from the encoder's AVCodecContext::extradata into the allocated buffer. AVCodecContext::extradata_size specifies size of this extradata buffer in bytes

rkudinov
  • 193
  • 13
0

Make sure that you are building correct packets. See how this is done in the ffmpeg: http://ffmpeg.org/doxygen/trunk/libx264_8c_source.html (static int encode_nals(AVCodecContext *ctx, AVPacket *pkt, x264_nal_t *nals, int nnal) and static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, int *got_packet))

pogorskiy
  • 4,705
  • 1
  • 22
  • 21
  • According what I have seen in encode_nals, the difference with my code is that I generate a packet per NAL, and encode_nals make a packet with a set of NALs... And also I fill steram_index, flags, pts and dts fiels of the packet. It's correct using one packet per nal? And about the others parameters... are correct? encode_nals doesn't fill them ( I want to stream in real-time ). About X264Frame, I encode using X264_encoder_encode and it returns to me directly the NALs. thx. – Raul Calvo Jan 15 '13 at 15:53
  • Ok, assuming this is incorrect, do you know how to obtain sei_size and sei data that is used in encode_nals function? I'm encoding with x264's library x264_encoder_encode, function that gives me the NALS. I don't have any AVCodecContext. If I try to encode with ffmpeg call to avcodec_find_encoder( CODEC_ID_H264 ) returns me NULL... – Raul Calvo Jan 17 '13 at 16:12
  • You can download the ffmpeg, or build it yourself with the libx264 codec. – pogorskiy Jan 18 '13 at 07:42
  • You can get `sei_size` and `sei` values as it is done in the function `X264_init` (http://ffmpeg.org/doxygen/trunk/libx264_8c_source.html). Forget `AVCodecContext`. It is used simply as a generic interface in ffmpeg. You do not need to create it for encoding. – pogorskiy Jan 18 '13 at 07:52
  • It's strange, encode_nals puts in the first of the data of the packet SEI data, but if I get the SEI data in the way is done on X264_init, I can get it from a NAL of type NAL_SEI ( the third NAL ). Encode_nals after writing the SEI data continue copying all the NALs, so the SEI data is twice in the packet data??? ( on the beginning of the packet data and also in the copy of the third NAL ) is this correct? it seems to be strange... – Raul Calvo Jan 18 '13 at 10:12
  • SEI data is copied only to the first frame (because it is set to zero in line 120) – pogorskiy Jan 18 '13 at 10:24
  • Ok, sorry,I didn't notice. But the only thing I must do in encode_nals is to write all the nal's payloads in the packet data,but moving the payload of the NAL_SEI nal to de beginning of the buffer? In original encode_nals is using the SEI data from encoder, but I have de SEI data in the third NAL. It's correct? Doing this, when I call avcodec_decode_video2 on the third time it stops in an assert . The first two calls seems to be ok, returning > 0 value. The assert is on mpegvideo.c and the line is "assert(s->last_picture_ptr==NULL || s->out_format != FMT_H264 || s->codec_id == CODEC_ID_SVQ3);" – Raul Calvo Jan 18 '13 at 11:17
  • I am dealing with the same problem. Let's say I now can get the data of a NAL unit (see spyandroid-ipcamera), then I want to use avcodec_decode_video2 to decode it. But avcodec_decode_video2 needs an input of AVCodecContext. Does this mean I could just pass a NULL avcodec_decode_video2? – user1914692 Jun 06 '13 at 18:56