java开发h265_MEDIACODEC在JNI层下的H264,H265视频硬解码实现(ACODEC )

{

char *source_path = (char *) (*env)->GetStringUTFChars(env, path, 0);

const char *mime = "video/avc";

int width = 1920;

int height = 1080;

bool b_direct_renderer = true;

if ((p_sys = calloc(1, sizeof(*p_sys))) == NULL)

return -1;

///Find Class and Get Method/Field

for (int i = 0; classes[i].name; i++) {

*(jclass*)((uint8_t*)p_sys + classes[i].offset) = (*env)->FindClass(env, classes[i].name);

if ((*env)->ExceptionOccurred(env)) {

printf("Unable to find class %s", classes[i].name);

(*env)->ExceptionClear(env);

goto error;

}

}

jclass last_class;

for (int i = 0; members[i].name; i++) {

if (i == 0 || strcmp(members[i].class, members[i - 1].class))

last_class = (*env)->FindClass(env, members[i].class);

if ((*env)->ExceptionOccurred(env)) {

printf("Unable to find class %s", members[i].class);

(*env)->ExceptionClear(env);

goto error;

}

switch (members[i].type) {

case METHOD:

*(jmethodID*)((uint8_t*)p_sys + members[i].offset) =

(*env)->GetMethodID(env, last_class, members[i].name, members[i].sig);

break;

case STATIC_METHOD:

*(jmethodID*)((uint8_t*)p_sys + members[i].offset) =

(*env)->GetStaticMethodID(env, last_class, members[i].name, members[i].sig);

break;

case FIELD:

*(jfieldID*)((uint8_t*)p_sys + members[i].offset) =

(*env)->GetFieldID(env, last_class, members[i].name, members[i].sig);

break;

}

if ((*env)->ExceptionOccurred(env)) {

printf("Unable to find the member %s in %s",

members[i].name, members[i].class);

(*env)->ExceptionClear(env);

goto error;

}

}

printf("// MEDIACODEC LIST\n");

int num_codecs = (*env)->CallStaticIntMethod(env, p_sys->media_codec_list_class,

p_sys->get_codec_count);

jobject codec_name = NULL;

for (int i = 0; i < num_codecs; i++) {

jobject info = NULL;

jobject name = NULL;

jobject types = NULL;

jsize name_len = 0;

const char *name_ptr = NULL;

int profile_levels_len = 0, num_types = 0;

bool found = false;

info = (*env)->CallStaticObjectMethod(env, p_sys->media_codec_list_class,

p_sys->get_codec_info_at, i);

if ((*env)->CallBooleanMethod(env, info, p_sys->is_encoder))

goto loopclean;

types = (*env)->CallObjectMethod(env, info, p_sys->get_supported_types);

num_types = (*env)->GetArrayLength(env, types);

name = (*env)->CallObjectMethod(env, info, p_sys->get_name);

name_len = (*env)->GetStringUTFLength(env, name);

name_ptr = (*env)->GetStringUTFChars(env, name, NULL);

found = false;

printf("MEDIACODEC::LIST#%s\n", name_ptr);

if (!strncmp(name_ptr, "OMX.google.", __MIN(11, name_len)))

goto loopclean;

for (int j = 0; j < num_types && !found; j++) {

jobject type = (*env)->GetObjectArrayElement(env, types, j);

if (!jstrcmp(env, type, mime)) {

found = true;

}

(*env)->DeleteLocalRef(env, type);

}

if (found) {

printf("using %.*s", name_len, name_ptr);

p_sys->name = malloc(name_len + 1);

memcpy(p_sys->name, name_ptr, name_len);

p_sys->name[name_len] = '\0';

codec_name = name;

}

loopclean:

if (name)

(*env)->ReleaseStringUTFChars(env, name, name_ptr);

if (types)

(*env)->DeleteLocalRef(env, types);

if (info)

(*env)->DeleteLocalRef(env, info);

if (found)

break;

}

printf("// MEDIACODEC\n");

if (!codec_name) {

printf("No suitable codec matching %s was found", mime);

goto error;

}

printf("// MEDIACODEC Create\n");

p_sys->codec = (*env)->CallStaticObjectMethod(env, p_sys->media_codec_class,

p_sys->create_by_codec_name, codec_name);

if ((*env)->ExceptionOccurred(env)) {

printf("Exception occurred in MediaCodec.createByCodecName.");

(*env)->ExceptionClear(env);

goto error;

}

p_sys->allocated = true;

p_sys->codec = (*env)->NewGlobalRef(env, p_sys->codec);

jobject format = (*env)->CallStaticObjectMethod(env, p_sys->media_format_class,

p_sys->create_video_format, (*env)->NewStringUTF(env, mime),

width, height);

printf("// MEDIACODEC Configure\n");

p_sys->direct_rendering = b_direct_renderer;

if (p_sys->direct_rendering) {

jobject surf = surface;

if (surf) {

(*env)->CallVoidMethod(env, p_sys->codec, p_sys->configure, format, surf, NULL, 0);

if ((*env)->ExceptionOccurred(env)) {

printf("Exception occurred in MediaCodec.configure");

(*env)->ExceptionClear(env);

goto error;

}

} else {

printf("Failed to get the Android Surface, disabling direct rendering.");

p_sys->direct_rendering = false;

}

}

if (!p_sys->direct_rendering) {

(*env)->CallVoidMethod(env, p_sys->codec, p_sys->configure, format, NULL, NULL, 0);

if ((*env)->ExceptionOccurred(env)) {

printf("Exception occurred in MediaCodec.configure");

(*env)->ExceptionClear(env);

goto error;

}

}

printf("// MEDIACODEC Start\n");

(*env)->CallVoidMethod(env, p_sys->codec, p_sys->start);

if ((*env)->ExceptionOccurred(env)) {

printf("Exception occurred in MediaCodec.start");

(*env)->ExceptionClear(env);

goto error;

}

p_sys->started = true;

p_sys->input_buffers = (*env)->CallObjectMethod(env, p_sys->codec, p_sys->get_input_buffers);

p_sys->output_buffers = (*env)->CallObjectMethod(env, p_sys->codec, p_sys->get_output_buffers);

p_sys->buffer_info = (*env)->NewObject(env, p_sys->buffer_info_class, p_sys->buffer_info_ctor);

p_sys->input_buffers = (*env)->NewGlobalRef(env, p_sys->input_buffers);

p_sys->output_buffers = (*env)->NewGlobalRef(env, p_sys->output_buffers);

p_sys->buffer_info = (*env)->NewGlobalRef(env, p_sys->buffer_info);

p_sys->i_output_buffers = (*env)->GetArrayLength(env, p_sys->output_buffers);

VideoDecoderStart(p_sys);

//receiver_start(source_path, 2);

return 0;

error:

if(p_sys != NULL)

{

free(p_sys);

p_sys = NULL;

}

return -1;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MediaCodec 是 Android 提供的一个用于音视频解码的 API,通过 MediaCodec 可以实现对 H.264 等常见视频格式的解码。下面是一个简单的使用 MediaCodec 解码 H.264 的示例: ```java // 创建 MediaCodec 对象 MediaCodec codec = MediaCodec.createDecoderByType("video/avc"); // 配置 MediaCodec,设置输入数据格式和输出数据 Surface MediaFormat format = MediaFormat.createVideoFormat("video/avc", width, height); format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible); codec.configure(format, surface, null, 0); // 启动 MediaCodec codec.start(); // 循环读取 H.264 数据并进行解码 while (decoding) { int inputBufferIndex = codec.dequeueInputBuffer(-1); if (inputBufferIndex >= 0) { ByteBuffer inputBuffer = codec.getInputBuffer(inputBufferIndex); // 将 H.264 数据写入 inputBuffer 中 codec.queueInputBuffer(inputBufferIndex, 0, data.length, presentationTimeUs, 0); } MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); int outputBufferIndex = codec.dequeueOutputBuffer(bufferInfo, 0); if (outputBufferIndex >= 0) { ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufferIndex); // 处理解码后的 YUV 数据 codec.releaseOutputBuffer(outputBufferIndex, true); } } ``` 需要注意的是,在使用 MediaCodec 解码 H.264 数据时,需要将 H.264 数据先解析成 NAL 单元,再将 NAL 单元写入到 inputBuffer 中进行解码。另外,解码后的数据是 YUV 格式的数据,需要根据实际需求进行处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值