标签:
#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 4098 #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.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; } 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 update_in_buffer; } 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->update_in_buffer = 1; 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, 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); } 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->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; } 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; }
标签:
原文地址:http://www.cnblogs.com/zhouLee/p/5148488.html