Reputation: 443
I'm trying to decode a video stream with ffmpeg library, that's how I do it basically:
void video_decode(const char *filename)
{
AVCodec *codec;
AVCodecContext *c= NULL;
int frame_count=0;
FILE *f;
AVFrame *frame;
uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
AVPacket avpkt;
av_init_packet(&avpkt);
memset(inbuf + INBUF_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE);
printf("Decoding video file...\n");
/* find the h264 video decoder */
codec = avcodec_find_decoder(AV_CODEC_ID_H264);
c = avcodec_alloc_context3(codec);
c->bit_rate = 400000;
c->width = 1920;
c->height = 1080;
if (avcodec_open2(c, codec, NULL) < 0) {
fprintf(stderr, "Could not open codec\n");
exit(1);
}
frame = av_frame_alloc();
for (;;) {
avpkt.size = fread(inbuf, 1, INBUF_SIZE, f);
if (avpkt.size == 0)
break;
avpkt.data = inbuf;
while(avpkt.size > 0){
int len, got_frame;
len = avcodec_decode_video2(c, frame, &got_frame, &avpkt);
if (len < 0) {
fprintf(stderr, "Errr while decding frame %d\n", frame_count);
exit (1);
}
if (got_frame) {
//Print out frame information..
}
if (avpkt.data) {
avpkt.size -= len;
avpkt.data += len;
}
}
}
}
But I got the following outputs:
Decoding video file...
[h264 @ 0x303c040] decode_slice_header error
[h264 @ 0x303c040] decode_slice_header error
[h264 @ 0x303c040] decode_slice_header error
[h264 @ 0x303c040] no frame!
Errr while decding frame 0
Obviously the initiation of codec was incomplete. Do you have experience with h264 api? Any help would be appreciated.
Upvotes: 1
Views: 14377
Reputation: 1
may be you should try to use AVCODECPARSER between your fread() and avcodec_decode_video2(); av_parser_parse2(). make your rawdata change into h264 fromat data to feed your decoder. C code like this :
#while (1)
{
cur_size = fread(in_buffer, 1, in_buffer_size, fp_in);
cur_ptr = in_buffer;
while (cur_size > 0)
{
int len = av_parser_parse2(pCodecParserCtx, pCodecCtx, &packet.data, &packet.size, cur_ptr, cur_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, AV_NOPTS_VALUE);
cur_ptr += len;
cur_size -= len;
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, &packet);
if (ret < 0)
{
printf("Decode Error\n");
return ret;
}
if (got_picture)
{
printf("Succeed to decode 1 frame!\n");
}
}
inspired by this : https://blog.csdn.net/leixiaohua1020/article/details/42181571
Upvotes: 0
Reputation: 565
The answer to this question is given under demuxing_decoding.c example of ffmpeg.
One can compile this file independently as below, if your ffmpeg installation directory is default "usr/local/".
gcc -I/usr/local/include -c demuxing_decoding.c -o demuxing_decoding.o
gcc demuxing_decoding.o -pthread -L/usr/local/lib -lavdevice -lavfilter -lpostproc -lavformat -lavcodec -lva-x11 -lva -lxcb-xfixes -lxcb-render -lxcb-shape -lxcb -lX11 -lx264 -lpthread -ldl -lz -lswresample -lswscale -lavutil -lm -o demuxing_decoding
In case, if the installation directory is changed to say something like "ffmpeg_ins_dir" replace "usr/local/" in above commands with "path upto ffmpef_ins_dir/".
Run the binary as below.
./demuxing_decoding test.h264 v_out.yuv a_out.yuv
Note : This example has many things you may not need at all, remove things that isn't needed and recompile it again.
Upvotes: 0
Reputation: 31101
You cant just put a random number (INBUF_SIZE ) of bytes into an AV packet. It should be a full AU or NALU, and if it is not annex B, you must first set the extra data field. For your case, I would recommend use libavformat to open the file and read the AVPackets.
Upvotes: 3