#include "hjcommon.hpp"
#include "x264.h"
#include "rtmp.h"
#include "faac.h"
extern "C" {
#include "queue.h"
}
// video
static x264_picture_t pic_in; // x264编码输入的图像
static x264_picture_t pic_out; // x264编码输出的图像
static int y_len, u_len, v_len; // Y U V 个数
static x264_t * video_encode_handle; // x264编码器
//线程处理
static pthread_mutex_t mutex;
static pthread_cond_t cond;
static bool is_pushing = FALSE; // 是否直播
static unsigned int start_time; //
static char *rtmp_path; // rtmp流媒体地址
// audio
static faacEncHandle audio_encode_handle; // faac音频编码处理器
static unsigned long nInputSamples; // 输入的采样个数
static unsigned long nMaxOutputBytes; // 编码输出之后的字节数
// 全局引用
static jobject jobj_push_native;
static jclass jcls_push_native;
static jmethodID jmid_throw_native_error;
static const int CONNECT_FAILED = 101;
static const int INIT_FAILED = 102;
/**
* 向Java层发送错误信息
*/
static void throwNativeError(JNIEnv *env,int code){
env->CallVoidMethod(jobj_push_native, jmid_throw_native_error, code);
}
/**
* 加入RTMPPacket队列,等待发送线程发送
*/
static void add_rtmp_packet(RTMPPacket *packet){
pthread_mutex_lock(&mutex);
if(is_pushing){
queue_append_last(packet);
}
pthread_cond_signal(&cond); // 修改线程条件,让pthread_cond_wait之后的代码继续执行,同一个pthread_cond_t可以重复的 signal 与 wait 操作
pthread_mutex_unlock(&mutex);
}
/**
* 添加AAC头信息
*/
static void add_aac_sequence_header(){
unsigned char *buf = 0; // 获取到的aac的头信息
unsigned long len; //长度
/*
int FAACAPI faacEncGetDecoderSpecificInfo( // 获取aac头信息
faacEncHandle hEncoder, // faac 编码器
unsigned char **ppBuffer, // 获取到的aac的头信息
unsigned long *pSizeOfDecoderSpecificInfo // 获取到的aac的头信息的长度
);
*/
faacEncGetDecoderSpecificInfo(audio_encode_handle, &buf, &len);
LOGD("faacEncGetDecoderSpecificInfo aac的头长度=%lu", len); // faacEncGetDecoderSpecificInfo aac的头长度=2
int body_size = 2 + len;
RTMPPacket *packet = (RTMPPacket *) malloc(sizeof(RTMPPacket));
//RTMPPacket初始化
RTMPPacket_Alloc(packet,body_size);
RTMPPacket_Reset(packet);
unsigned char * body = (unsigned char *) packet->m_body;
//头信息配置
/*AF 00 + AAC RAW data*/
body[0] = 0xAF;//10 5 SoundFormat(4bits):10=AAC 5 = Nellymoser 8 kHz mono,SoundRate(2bits):3=44kHz,SoundSize(1bit):1=16-bit samples,SoundType(1bit):1=Stereo sound
body[1] = 0x00;//AACPacketType:0表示AAC sequence header
memcpy(&body[2], buf, len); /*spec_buf是AAC sequence header数据*/
packet->m_packetType = RTMP_PACKET_TYPE_AUDIO;
packet->m_nBodySize = body_size;
packet->m_nChannel = 0x04;
packet->m_hasAbsTimestamp = 0;
packet->m_nTimeStamp = 0;
packet->m_headerType = RTMP_PACKET_SIZE_MEDIUM;
add_rtmp_packet(packet);
free(buf);
}
/**
* 添加AAC rtmp packet
*/
static void add_aac_body(unsigned char *buf, int len){
int body_size = 2 + len; // 多配置的2个字节,为 AAC header 的长度
RTMPPacket *packet = (RTMPPacket *) malloc(sizeof(RTMPPacket));
//RTMPPacket初始化
RTMPPacket_Alloc(packet, body_size);
RTMPPacket_Reset(packet);
unsigned char * body = (unsigned char *) packet->m_body;
//头信息配置
/*AF 00 + AAC RAW data*/
body[0] = 0xAF;//10 5 SoundFormat(4bits):10=AAC 5 = Nellymoser 8 kHz mono,SoundRate(2bits):3=44kHz,SoundSize(1bit):1=16-bit samples,SoundType(1bit):1=Stereo sound
body[1] = 0x01;//AACPacketType:1表示AAC raw ,即 AAC 音频数据
memcpy(&body[2], buf, len); /*spec_buf是AAC raw数据*/
packet->m_packetType = RTMP_PACKET_TYPE_AUDIO;
packet->m_nBodySize = body_size;
packet->m_nChannel = 0x04;
packet->m_hasAbsTimestamp = 0;
packet->m_headerType = RTMP_PACKET_SIZE_LARGE;
packet->m_nTimeStamp = RTMP_GetTime() - start_time;
add_rtmp_packet(packet);
}
/**
* 从队列中不断拉取RTMPPacket发送给流媒体服务器)
*/
static void *push_thread(void * arg){
JNIEnv* env = 0;//获取当前线程JNIEnv
hj_javavm->AttachCurrentThread(&env, NULL);
//建立RTMP连接
RTMP *rtmp = RTMP_Alloc(); // 创建 RTMP
if(!rtmp){
LOGE("rtmp初始化失败");
goto end;
}
RTMP_Init(rtmp); // 初始化 RTMP
rtmp->Link.timeout = 5; //连接超时的时间,单位秒
//设置流媒体地址
RTMP_SetupURL(rtmp, rtmp_path);
//发布rtmp数据流
RTMP_EnableWrite(rtmp);
//
(十四) x264视频编码、faac音频编码、rtmpdump推流
最新推荐文章于 2023-12-27 23:21:22 发布