x264软编码(jni接口)

这篇博客深入探讨了x264软编码技术,通过JNI接口在Android平台上实现高效视频编码。内容涵盖x264编码库的使用、JNI接口设计与调用、以及在实际应用中的性能优化策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链接地址:http://download.youkuaiyun.com/detail/yuanchunsi/9895103



//  x264.c
//  jni
//
//  
//  create by yuanchunsi.



#include <jni.h>  
#include <stdio.h>  
#include <string.h>  
#include <stdlib.h>  
#include <arpa/inet.h>  
#include <stdbool.h>  
#include <pthread.h>  

#include "stdint.h"  
#include "utils_jni.h"  
#include "utils/log.h"
#include "utils/queue.h"



#if defined ( __cplusplus)  
extern "C"  
{  
#include "x264.h"  
};  
#else  
#include "x264.h"  
#endif  

typedef struct _Encoder{  
  x264_param_t * param;  
  x264_t *handle;  
  x264_picture_t * picture;  
  x264_nal_t  *nal;  
} Encoder; 

typedef struct _packet{
  char *in;
  int insize;
} packet_t;


Encoder * encoder = NULL;
static queue_t * queue = NULL;
static pthread_t encoder_id;
static bool encoder_stop ;
static FILE* fp_dst = NULL;

static void* encoder_run(void *data) {

  int ret;  
  int y_size;  
  //int i,j;  
  //int iNal   = -1;  
  //int frame_num = 0;

  pthread_detach(pthread_self());


  pthread_t thid;
  struct sched_param param;
  thid = pthread_self();
  param.sched_priority = sched_get_priority_max(SCHED_RR);
  pthread_setschedparam(thid,SCHED_RR,¶m);


  Encoder *en = (Encoder*)data;
  if (NULL == en) {
    ERROR("Invaid data\n");
    return NULL;
  }
  //fp_dst = fopen("/mnt/sdcard/eques/test.h264", "ab");  
  x264_picture_t pPic_out ;  
  packet_t packet;
  y_size = en->param->i_width * en->param->i_height; 
  while(queue->ndata < 5) {
    WARN("queue is free,waiting for....\n");
    usleep(10*1000);
  }

  while(!encoder_stop) {

    int i = 0;
    int j = 0;  
    int iNal   = -1;
    int frame_num = 0;
  
    memset(&packet,0,sizeof(packet_t));
    fp_dst = fopen("/mnt/sdcard/test.h264", "ab");  
    ret = queue_peek(queue,&packet,sizeof(packet_t));
    if(0 != ret) {
      usleep(30*1000);
      continue;
    }

    /*---------------------detect frame number------------------*/   
    if(frame_num==0){
      switch(en->param->i_csp){  
        case X264_CSP_I444:frame_num=packet.insize/(y_size*3);break;  
        case X264_CSP_I420:frame_num=packet.insize/(y_size*3/2);break;  
        default:ERROR("Colorspace Not Support.\n");return NULL;  
      }  
    }   
    /*---------------------Loop to Encode------------------*/   
    for( i=0;i<frame_num;i++) {  
      switch(en->param->i_csp){  
        case X264_CSP_I444:{  
                             memcpy(en->picture->img.plane[0],packet.in,y_size);//Y  
                             memcpy(en->picture->img.plane[1],packet.in+y_size,y_size);//U  
                             memcpy(en->picture->img.plane[2],packet.in+y_size+y_size,y_size);//V  
                             break; 
                           }  
        case X264_CSP_I420:{  
                             memcpy(en->picture->img.plane[0],packet.in,y_size);//Y 
                             memcpy(en->picture->img.plane[1],packet.in+y_size,y_size/4);//U  
                             memcpy(en->picture->img.plane[2],packet.in+y_size+(y_size/4),y_size/4);//V  
                             break;
                           }  
        default:{  
                  ERROR("Colorspace Not Support.\n");  
                  encoder_stop = true;
                  return NULL;
                }  
      }
      en->picture->i_pts = i;  
#if 1
      ret = x264_encoder_encode(en->handle, &(en->nal), &iNal, en->picture,&pPic_out);  
      if (ret < 0) {  
        ERROR("x264 encoder encode error.\n");  
        encoder_stop = true;
        return NULL;  
      }  
      for ( j = 0; j < iNal; ++j) {
        fwrite(en->nal[j].p_payload, 1,en->nal[j].i_payload, fp_dst);  
      }
#endif  
    }  

    fclose(fp_dst);
    fp_dst = NULL;
    INFO("Encode dnoe\n");
  }

}

JNIEXPORT jlong Java_com_eques_device_ui_hardware_X264JNI_X264CompressBegin(JNIEnv* env,jobject thiz,jint width, jint height) {  

  int type = 1;
  int csp = 0;
  if (1 == type) {
    csp = X264_CSP_I420;  
  } else if (2 == type) {
    csp = X264_CSP_I444;
  }
  //Encoder * encoder = (Encoder *)malloc(sizeof(Encoder));  
  encoder = (Encoder *)malloc(sizeof(Encoder));  
  encoder->param = (x264_param_t *)malloc(sizeof(x264_param_t));  
  encoder->picture = (x264_picture_t *)malloc(sizeof(x264_picture_t));  
  x264_param_default(encoder->param); //set default param  

  encoder->param->i_csp=csp;   
  encoder->param->i_width = width; //set frame width  
  encoder->param->i_height = height; //set frame
  encoder->param->i_log_level = X264_LOG_NONE;  
  encoder->param->i_threads  = 4; // 4 cpu kernel
/*
  encoder->param->rc.i_lookahead =0;  
  encoder->param->rc.i_rc_method = X264_RC_CQP;  
  encoder->param->i_log_level = X264_LOG_NONE;  
  encoder->param->i_bframe=0;  
  encoder->param->i_fps_num =5;  
  encoder->param->i_fps_den = 1;  
*/
  x264_param_apply_profile(encoder->param, x264_profile_names[0]);  
  if ((encoder->handle = x264_encoder_open(encoder->param)) == 0) { 
    ERROR("x264_econder_open failed\n"); 
    return  0;  
  }

  /* Create a new pic  */  
  x264_picture_alloc(encoder->picture,X264_CSP_I420,encoder->param->i_width,encoder->param->i_height);  
  //fp_dst = fopen("/mnt/sdcard/eques/test.h264", "ab");
  
  if (0 != queue_create(&queue,sizeof(packet_t),300)) {
    ERROR("queue create failed\n"); 
    return -1;
  }

  if (0 != pthread_create(&encoder_id,NULL,encoder_run,encoder)){
    ERROR("pthread create failed\n"); 
    return -1;
  }
  encoder_stop = false;

  INFO("x264Encoder CompressBegin done\n");

  return (jlong)PTR(encoder);  
}  

JNIEXPORT jint Java_com_eques_device_ui_hardware_X264JNI_X264CompressEnd(JNIEnv* env,jobject thiz,jlong handle)  
{  
  Encoder* en  =   (Encoder *)PTR(handle);  
  encoder_stop = true;
  if(en->picture)  
  {  
    x264_picture_clean(en->picture);  
    free(en->picture);  
    en->picture = 0;  
  }  
  if(en->param)  
  {  
    free(en->param);  
    en->param=0;  
  }  
  if(en->handle)  
  {  
    x264_encoder_close(en->handle);  
  }  
  free(en);  
  queue_destroy(queue);
  en = NULL;
  queue = NULL;

  //fclose(fp_dst);
  //fp_dst = NULL;
  INFO("x264Encoder CompressEnd done\n");

  return 0;  
}

JNIEXPORT jint Java_com_eques_device_ui_hardware_X264JNI_X264CompressBuffer(JNIEnv* env,jobject thiz,jlong handle,jbyteArray DataIn,jint insize)  
{  
  if (0 == handle || NULL == DataIn || 0 > insize) {
    ERROR("Invaild data\n");
    return -1;
  }

  int ret = 0;
  Encoder* en  =   (Encoder *)PTR(handle);
  packet_t* packet = (packet_t*)malloc(sizeof(packet_t));  
  packet->in = (char*)(*env)->GetByteArrayElements(env,DataIn,NULL);
  if (NULL == packet->in) {
    ERROR("NO data input\n");
    return -1;
  }else {
    packet->insize = insize; 
    INFO("Get data success\n");
  }
  if (queue->ndata >250) {
    WARN("queue is full ,waiting for....\n");
    usleep(30*1000);
  }
  ret = queue_write(queue,(void*)packet,sizeof(packet_t));
  if (0 != ret) {
    return -1;
  }
  
  (*env)->ReleaseByteArrayElements(env,DataIn,packet->in,0);

  INFO("x264Encoder Compressbuffer done\n");
  return ret;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值