#include "libavcodec/avcodec.h"#include"libswscale/swscale.h"#include"libavutil/opt.h"#include"libavutil/imgutils.h"#include#include#include#includetypedefenum{
FALSE= 0, TRUE = 1,
} C_BOOL;
typedef unsignedcharuint8_t;#define IN_BUFFER_SIZE 4098
#define LOGE(format, ...) __android_log_print(ANDROID_LOG_ERROR, "(>_
#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.rgb24";
FILE*fp_out = fopen(filepath_out, "wb");if (NULL ==fp_out)
{
LOGE("open output yuv 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;
}
typedefstruct{
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;intcur_size;intfirst_time;intgot_picture;intupdate_in_buffer;
} H264DecodeHandler;
JNIEXPORT jint JNICALL Java_com_zhoulee_h264decoder_MainActivity_InitH264Decoder(JNIEnv*env, jobject obj)
{return 0;
}intInitH264Decoder()
{
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->update_in_buffer = 1;return (int) handle;
}void ReleaseH264Decoder(intdecodeHandle)
{
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)
{
}
typedefenum{
DecFailed= 0, DecSuccess = 1, DecNeedMoreData = 2,
} DECODERESULT;
DECODERESULT DecodeOneFrame(intdecodeHandle)
{
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");returnDecNeedMoreData;
}int decode_ret = avcodec_decode_video2(handle->pCodecCtx, handle->pFrame, &(handle->got_picture),&(handle->packet));if (decode_ret < 0)
{
LOGE("avcodec_decode_video2 failed");returnDecFailed;
}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, AV_PIX_FMT_RGB24,
SWS_BICUBIC, NULL, NULL, NULL);
handle->pRGBFrame =av_frame_alloc();
handle->out_buffer = (uint8_t *) av_malloc(
avpicture_get_size(AV_PIX_FMT_RGB24, handle->pCodecCtx->width, handle->pCodecCtx->height));
avpicture_fill((AVPicture*) handle->pRGBFrame, handle->out_buffer, AV_PIX_FMT_RGB24,
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);
}returnDecSuccess;
}
DECODERESULT DecodeH264ToRGB(int decodeHandle, uint8_t* in_buffer, int in_len, uint8_t** out_buffer, int*out_len)
{
H264DecodeHandler* handle = (H264DecodeHandler*) decodeHandle;if(handle->update_in_buffer == 1)
{
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 * 3;
}if (handle->cur_size == 0)
{
handle->update_in_buffer = 1;
}else{
handle->update_in_buffer = 0;
}returndecode_result;
}
C_BOOL __DecodeH264Video(FILE* fp_in, FILE*fp_out)
{
H264DecodeHandler* handle = (H264DecodeHandler*) InitH264Decoder();if (handle ==NULL)
{
LOGE("init h264 decoder failed");returnFALSE;
}
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);returnTRUE;
}