zoukankan      html  css  js  c++  java
  • H264转成RGB24格式-2016.01.21

    #include "libavcodec/avcodec.h"
    #include "libswscale/swscale.h"
    #include "libavutil/opt.h"
    #include "libavutil/imgutils.h"
    #include <stdio.h>
    #include <string.h>
    #include <jni.h>
    #include <android/log.h>
    
    typedef enum
    {
        FALSE = 0, TRUE = 1,
    } C_BOOL;
    
    typedef unsigned char uint8_t;
    
    #define  IN_BUFFER_SIZE  2048
    #define TARGET_VIDEO_TYPE AV_PIX_FMT_RGB565
    
    #define LOGE(format, ...)  __android_log_print(ANDROID_LOG_ERROR, "(>_<)", format, ##__VA_ARGS__)
    #define LOGD(format, ...)  __android_log_print(ANDROID_LOG_DEBUG, "(-_-)", format, ##__VA_ARGS__)
    
    static C_BOOL __DecodeH264Video(FILE* fp_in, FILE* fp_out);
    
    JNIEXPORT jboolean JNICALL Java_com_zhoulee_h264decoder_MainActivity_DecodeH264Video(JNIEnv *env, jobject obj)
    {
        char filepath_in[] = "/data/video/bxjg_352x288.h264";
        FILE *fp_in = fopen(filepath_in, "rb");
        if (NULL == fp_in)
        {
            LOGE("open input h264 video file failed, filename [%s]", filepath_in);
            return (jboolean) FALSE;
        }
    
        char filepath_out[] = "/data/video/bxjg_352x288.rgb565";
        FILE *fp_out = fopen(filepath_out, "wb");
        if (NULL == fp_out)
        {
            LOGE("open output rgb video file failed, filename [%s]", filepath_out);
            return (jboolean) FALSE;
        }
    
        LOGD("open input and output file success");
    
        if (TRUE == __DecodeH264Video(fp_in, fp_out))
        {
            LOGD("decode h264 video success");
        }
        else
        {
            LOGE("decode h264 video failed");
            return (jboolean) FALSE;
        }
    
        fclose(fp_in);
        fclose(fp_out);
    
        return (jboolean) TRUE;
    }
    
    typedef struct
    {
        AVCodec *pCodec;
        AVCodecContext *pCodecCtx;
        AVCodecParserContext *pCodecParserCtx;
        AVFrame *pFrame;
        AVFrame *pRGBFrame;
        struct SwsContext *img_convert_ctx;
        uint8_t *out_buffer;
        uint8_t *cur_ptr;
        AVPacket packet;
        int cur_size;
        int first_time;
        int got_picture;
        int dst_bpp; //bytes of pixel of destination format
    } H264DecodeHandler;
    
    JNIEXPORT jint JNICALL Java_com_zhoulee_h264decoder_MainActivity_InitH264Decoder(JNIEnv *env, jobject obj)
    {
        return 0;
    }
    
    int InitH264Decoder()
    {
        H264DecodeHandler *handle = (H264DecodeHandler*) malloc(sizeof(H264DecodeHandler));
        if (NULL == handle)
        {
            LOGE("malloc H264DecodeHandler failed");
            return 0;
        }
    
        avcodec_register_all();
        handle->pCodec = avcodec_find_decoder(AV_CODEC_ID_H264);
        if (NULL == handle->pCodec)
        {
            LOGE("avcodec_find_decoder failed");
            return 0;
        }
    
        handle->pCodecCtx = avcodec_alloc_context3(handle->pCodec);
        if (NULL == handle->pCodecCtx)
        {
            LOGE("avcodec_alloc_context3 failed");
            return 0;
        }
    
        handle->pCodecParserCtx = av_parser_init(AV_CODEC_ID_H264);
        if (NULL == handle->pCodecParserCtx)
        {
            LOGE("av_parser_init failed");
            return 0;
        }
    
        if (avcodec_open2(handle->pCodecCtx, handle->pCodec, NULL) < 0)
        {
            LOGE("avcodec_open2 failed");
            return 0;
        }
    
        handle->pFrame = av_frame_alloc();
        if (NULL == handle->pFrame)
        {
            LOGE("av_frame_alloc failed");
            return 0;
        }
    
        av_init_packet(&(handle->packet));
    
        handle->cur_size = 0;
        handle->got_picture = 0;
        handle->first_time = 1;
        handle->dst_bpp = av_get_bits_per_pixel(av_pix_fmt_desc_get(TARGET_VIDEO_TYPE)) / 8;
    
        LOGD("bytes of pixel of destination format is [%d]", handle->dst_bpp);
    
        return (int) handle;
    }
    
    void ReleaseH264Decoder(int decodeHandle)
    {
        H264DecodeHandler* handle = (H264DecodeHandler*) decodeHandle;
        sws_freeContext(handle->img_convert_ctx);
        av_frame_free(&(handle->pRGBFrame));
        av_parser_close(handle->pCodecParserCtx);
        av_frame_free(&(handle->pRGBFrame));
        avcodec_close(handle->pCodecCtx);
        av_free(handle->pCodecCtx);
        free(handle);
    }
    
    JNIEXPORT jint JNICALL Java_com_zhoulee_h264decoder_MainActivity_ReleaseH264Decoder(JNIEnv *env, jobject obj,
            jint handle)
    {
    
    }
    
    typedef enum
    {
        DecFailed = 0, DecSuccess = 1, DecNeedMoreData = 2,
    } DECODERESULT;
    
    DECODERESULT DecodeOneFrame(int decodeHandle)
    {
        H264DecodeHandler* handle = (H264DecodeHandler*) decodeHandle;
    
        int parse_len = av_parser_parse2(handle->pCodecParserCtx, handle->pCodecCtx, &(handle->packet.data),
                &(handle->packet.size), handle->cur_ptr, handle->cur_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, AV_NOPTS_VALUE);
    
        LOGD("current size is [%d], parse size is [%d], handle->packet.size [%d]",
                handle->cur_size, parse_len, handle->packet.size);
    
        handle->cur_ptr += parse_len;
        handle->cur_size -= parse_len;
    
        if (0 == handle->packet.size)
        {
            LOGD("handle->packet.size is 0, need read more data");
            return DecNeedMoreData;
        }
    
        int decode_ret = avcodec_decode_video2(handle->pCodecCtx, handle->pFrame, &(handle->got_picture),
                &(handle->packet));
    
        if (decode_ret < 0)
        {
            LOGE("avcodec_decode_video2 failed");
            return DecFailed;
        }
    
        if (handle->got_picture)
        {
            if (handle->first_time)
            {
                LOGD("CodecCtx->codec->long_name [%s]", handle->pCodecCtx->codec->long_name);
                LOGD("CodecCtx->width [%d], CodecCtx->height [%d]", handle->pCodecCtx->width, handle->pCodecCtx->height);
    
                handle->img_convert_ctx = sws_getContext(handle->pCodecCtx->width, handle->pCodecCtx->height,
                        handle->pCodecCtx->pix_fmt, handle->pCodecCtx->width, handle->pCodecCtx->height, TARGET_VIDEO_TYPE,
                        SWS_BICUBIC, NULL, NULL, NULL);
    
                handle->pRGBFrame = av_frame_alloc();
    
                handle->out_buffer = (uint8_t *) av_malloc(
                        avpicture_get_size(TARGET_VIDEO_TYPE, handle->pCodecCtx->width, handle->pCodecCtx->height));
    
                avpicture_fill((AVPicture *) handle->pRGBFrame, handle->out_buffer, TARGET_VIDEO_TYPE,
                        handle->pCodecCtx->width, handle->pCodecCtx->height);
    
                handle->first_time = 0;
            }
    
            sws_scale(handle->img_convert_ctx, (const uint8_t* const *) handle->pFrame->data, handle->pFrame->linesize, 0,
                    handle->pCodecCtx->height, handle->pRGBFrame->data, handle->pRGBFrame->linesize);
        }
    
        return DecSuccess;
    }
    
    DECODERESULT DecodeH264ToRGB(int decodeHandle, uint8_t* in_buffer, int in_len, uint8_t** out_buffer, int* out_len)
    {
        H264DecodeHandler* handle = (H264DecodeHandler*) decodeHandle;
    
        if(handle->cur_size == 0)
        {
            handle->cur_ptr = in_buffer;
            handle->cur_size = in_len;
        }
    
        DECODERESULT decode_result = DecodeOneFrame((int) handle);
    
        if (DecSuccess == decode_result)
        {
            *out_buffer = handle->pRGBFrame->data[0];
            *out_len = handle->pCodecCtx->width * handle->pCodecCtx->height * handle->dst_bpp;
        }
    
        return decode_result;
    }
    
    C_BOOL __DecodeH264Video(FILE* fp_in, FILE* fp_out)
    {
        H264DecodeHandler* handle = (H264DecodeHandler*) InitH264Decoder();
        if (handle == NULL)
        {
            LOGE("init h264 decoder failed");
            return FALSE;
        }
    
        uint8_t in_buffer[IN_BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
        memset(in_buffer, 0, sizeof(in_buffer));
    
        C_BOOL need_read_from_file = TRUE;
        int read_size = 0;
        int frame_index = 0;
        uint8_t* out_buffer = NULL;
        int out_len = 0;
        while (TRUE)
        {
            if (need_read_from_file == TRUE)
            {
                if ((read_size = fread(in_buffer, 1, IN_BUFFER_SIZE, fp_in)) == 0)
                {
                    LOGD("read all data from file, end!!!");
                    break;
                }
                LOGD("read from file size is [%d]", read_size);
            }
    
            DECODERESULT decode_result = DecodeH264ToRGB((int) handle, in_buffer, read_size, &out_buffer, &out_len);
    
            if (DecFailed == decode_result)
            {
                LOGE("decode one frame failed");
                break;
            }
    
            if (DecSuccess == decode_result)
            {
                fwrite(out_buffer, 1, out_len, fp_out);
                ++frame_index;
                LOGD("succeed to decode one frame, frame index [%d]", frame_index);
            }
    
            if (DecNeedMoreData == decode_result)
            {
                need_read_from_file = TRUE;
            }
            else
            {
                need_read_from_file = FALSE;
            }
        }
    
        ReleaseH264Decoder((int) handle);
    
        return TRUE;
    }
  • 相关阅读:
    singleton 单例模式
    try catch finall 结构里的 return
    ConcurrentHashMap
    ConcurrentHashMap原理分析
    Java 实现两个整数变量的交换
    Java reflect 反射 3 Class.forname
    Java reflect 反射 2
    Java reflect 反射 1
    java class load 类加载
    HashMap源码解析
  • 原文地址:https://www.cnblogs.com/zhouLee/p/5148488.html
Copyright © 2011-2022 走看看