FFmpeg decoding H264 raw data stream __YUV

Source: Internet
Author: User

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-&GT;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-&GT;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-&GT;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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.