(十四) x264视频编码、faac音频编码、rtmpdump推流

#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);
	//
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值