Believe that a lot of people in the first contact with FFmpeg, want to ffmpeg API are very cumbersome, because of their own code is larger, more modules, more APIs, and in the FFmpeg routines are the file's driving into the codec, So want to achieve a simple pure data stream decoding will feel the start; This paper describes the decoding of a complete H264 data into a yuyv format.
FFmpeg version: ffmpeg-3.1.2
The FFmpeg libraries used include: Libavformat, LIBAVCODEC, Libavutil external interface:
The initial decoding device, codec_id for the selected decoder
int initdecoder (int codec_id);
Incoming parameters: Framedata, Framelen for H264 data source and data length
//Out parameters: Outputframe for the decoded YUYV data store, WIDTH/HEIGHT/PIXFMT returns the video wide/high/decoded data format,
int decodeframe (unsigned char * framedata, int framelen,//input
unsigned char *outputframe, int *width, int * Height, int *pixfmt);//output
//parameter meaning the same interface, which is to brush the cache data in the decoder out of the
int decodeframeflush (unsigned char *outputframe, int *width, int *height, int *pixfmt);//output
//Cleaning decoder request resource
void uninitdecoder (void);
header files and variables:
#include <libavutil/imgutils.h>
#include <libavutil/samplefmt.h>
#include <libavutil/ timestamp.h>
#include <libavformat/avformat.h>
#include "socket_lib.h"
static Avcodec *codec = NULL;
static Avcodeccontext *codec_ctx= NULL;
static Avframe *frame = NULL;
Static Avpacket avpkt;
static bool codecinited = FALSE;
Decoder initialization:
int initdecoder (int codec_id) {if (codecinited!= false) {printf ("Decoder inited fail\n");
return-1;
} avcodec_register_all ();
codec = Avcodec_find_decoder (codec_id);
if (!codec) {printf ("Avcodec_find_decoder fail\n");
return-1;
} Codec_ctx = Avcodec_alloc_context3 (codec);
if (!codec_ctx) {printf ("Avcodec_alloc_context3 fail\n");
return-1;
}/* else {codec_ctx->time_base.num = 1; Codec_ctx->frame_number = 1;
One video frame per packet Codec_ctx->codec_type = Avmedia_type_video;
codec_ctx->bit_rate = 0; Codec_ctx->time_base.den = den;//Frame rate Codec_ctx->width = width;//Video Width codec_ctx->height = height;//video High}*/if (
Avcodec_open2 (Codec_ctx, codec, NULL) < 0) {printf ("Avcodec_open2 fail\n");
return-1;
frame = Av_frame_alloc ();
if (!frame) {printf ("Av_frame_alloc fail\n");
return-1;
} av_init_packet (&AVPKT);
Codecinited = true;
return 0; }
Decode a Frame H264 video: After successfully decoding this interface will return the video's wide, high, decoded data format (yuv420 or yuv422, etc.)
int decodeframe (unsigned char * framedata, int framelen,//input
unsigned char *outputframe, int *width, int *heigh T, int *pixfmt)//output
{
avpkt.size = Framelen;
Avpkt.data = Framedata;
while (avpkt.size > 0)
{
if (Decode_frame (Codec_ctx, frame, &avpkt, 0, Outputframe) < 0)
{
printf ("%s decode fail\n", __func__);
Return-1
}
}
*width = codec_ctx->width;
*height = codec_ctx->height;
*PIXFMT = codec_ctx->pix_fmt;
return 0;
}
Decode a frame of detailed operation (here just did the yuv422p processing):
static int Decode_frame (Avcodeccontext *avctx,avframe *frame,//input avpacket *pkt, int last,//input unsigned char
*outputframe)//output {int len = 0;
int got_frame = 0;
if (!codecinited) {printf ("%s decoder uninted\n", __func__);
return-1;
Len = Avcodec_decode_video2 (Avctx, Frame, &got_frame, PKT);
if (Len < 0) {printf ("Error while decoding frames\n");
return Len;
} if (got_frame) {switch (AVCTX->PIX_FMT) {case av_pix_fmt_yuv422p: {int index = 0;
int y_i = 0, u_i = 0, v_i = 0;
for (index = 0; index < frame->width*frame->height*2;)
{outputframe[index++] = frame->data[0][y_i++];
outputframe[index++] = frame->data[1][u_i++];
outputframe[index++] = frame->data[0][y_i++];
outputframe[index++] = frame->data[2][v_i++];
}}break;
Default: {return-1; }} if (Pkt->data) {pkt->size = Len;
Pkt->data = Len;
return 0; }Because Avcodec_decode_video2 this interface is discarded by ffmpeg, you can use the new interface://20180329 add
int decodeframe (unsigned char * framedata, int framelen,//input unsigned char *outputframe, int *width, int *height, int
*PIXFMT)//output {avpkt.size = Framelen;
Avpkt.data = Framedata; if (Avcodec_send_packet (Codec_ctx, &avpkt)) { printf ("%s%d
Avcodec_send_packet fail\n ", __func__,__line__);
return-1; } if (Avcodec_receive_frame (Codec_ctx, frame)) { printf ("%s%d
Avcodec_receive_frame fail\n ", __func__, __line__);
return-1; } switch (CODEC_CTX->PIX_FMT) { case av_pix_fmt_yuv422p: {
int index = 0; int y_i = 0, u_i = 0, v_i = 0; for (index = 0; index < frame->
Width*frame->height * 2;) { outputframe[
index++] = frame->data[0][y_i++]; outputframe[
index++] = frame->data[1][u_i++]; outputframe[
index++] = frame->data[0][y_i++]; outputframe[
index++] = frame->data[2][v_i++]; } }bReak; default: { printf ("
Default format:%d\n ", CODEC_CTX->PIX_FMT);
return-1; }
*width = codec_ctx->width;
*height = codec_ctx->height;
*pixfmt = codec_ctx->pix_fmt;
return 0; }After decoding is complete, brush out the data in the decoder:
int Decodeframeflush (unsigned char *outputframe, int *width, int *height, int *pixfmt)//output
{
if (!codecinite D)
{
printf ("%s decoder uninted\n", __func__);
return-1;
}
Avpkt.data = NULL;
avpkt.size = 0;
if (Decode_frame (Codec_ctx, Frame, &avpkt, 1, Outputframe) < 0)
return-1;
*width = codec_ctx->width;
*height = codec_ctx->height;
*PIXFMT = codec_ctx->pix_fmt;
return 0;
}
To release the decoder resource:
void Uninitdecoder (void)
{
if (codecinited)
{
avcodec_close (codec_ctx);
Av_free (CODEC_CTX);
Av_frame_free (&frame);
codecinited = false;
}
}
There are downloads for related resources:
http://download.csdn.net/download/xushan239/10199075http://download.csdn.net/download/xushan239/10190449