1. 程式人生 > >android librtmp 推送h264流 aac流 基本過程總結四 推流x264

android librtmp 推送h264流 aac流 基本過程總結四 推流x264

{
	RTMPPacket * packet;
	unsigned char * body;
	int i;
	int ret = 0;
	if (m_pRtmp == NULL)
		return -1;
	
	packet = (RTMPPacket *) malloc(RTMP_HEAD_SIZE + 1024);
	memset(packet, 0, RTMP_HEAD_SIZE);

	packet->m_body = (char *) packet + RTMP_HEAD_SIZE;
	body = (unsigned char *) packet->m_body;
	i = 0;
	body[i++] = 0x17;
	body[i++] = 0x00;

	body[i++] = 0x00;
	body[i++] = 0x00;
	body[i++] = 0x00;

	/*AVCDecoderConfigurationRecord*/
	body[i++] = 0x01;
	body[i++] = sps[1];
	body[i++] = sps[2];
	body[i++] = sps[3];
	body[i++] = 0xff;

	/*sps*/
	body[i++] = 0xe1;
	body[i++] = (sps_len >> 8) & 0xff;
	body[i++] = sps_len & 0xff;
	memcpy(&body[i], sps, sps_len);

	i += sps_len;

	/*pps*/
	body[i++] = 0x01;
	body[i++] = (pps_len >> 8) & 0xff;
	body[i++] = (pps_len) & 0xff;
	memcpy(&body[i], pps, pps_len);
	i += pps_len;

	packet->m_packetType = RTMP_PACKET_TYPE_VIDEO;
	packet->m_nBodySize = i;
	packet->m_nChannel = 0x04;

	packet->m_nTimeStamp = 0;
	packet->m_hasAbsTimestamp = 0;
	packet->m_headerType = RTMP_PACKET_SIZE_MEDIUM;
	packet->m_nInfoField2 = m_pRtmp->m_stream_id;

	if (RTMP_IsConnected(m_pRtmp)) 
	{
		//呼叫傳送介面
		int success = RTMP_SendPacket(m_pRtmp, packet, TRUE);
		if (success != 1) 
		{
			dm_printf("send_video_sps_pps fail");
			ret = -1;
		}
	}
	else
		ret = -1;
	free(packet);
	return ret;
}

5.rtmp傳送普通的NAL

static int send_rtmp_video(RTMP* m_pRtmp, unsigned char *data, int data_len, int timestamp) 
{
	int type;
	RTMPPacket * packet;
	unsigned char * body;
	unsigned char* buffer = data;
	unsigned int length = data_len;
	int ret = 0;
	if (m_pRtmp == NULL)	
		return -1;

	/*去掉幀界定符(這裡可能2種,但是sps or  pps只能為 00 00 00 01)*/
	if (buffer[2] == 0x00) { /*00 00 00 01*/
		buffer += 4;
		length -= 4;
	} else if (buffer[2] == 0x01) { /*00 00 01*/
		buffer += 3;
		length -= 3;
	}
	type = buffer[0] & 0x1f;

	packet = (RTMPPacket *) malloc(RTMP_HEAD_SIZE + length + 9);
	memset(packet, 0, RTMP_HEAD_SIZE);

	packet->m_body = (char *) packet + RTMP_HEAD_SIZE;
	packet->m_nBodySize = length + 9;

	/*send video packet*/
	body = (unsigned char *) packet->m_body;
	memset(body, 0, length + 9);

	/*key frame*/
	body[0] = 0x27;
	if (type == NAL_SLICE_IDR) //此為關鍵幀
	{
		body[0] = 0x17;
	}

	body[1] = 0x01; /*nal unit*/
	body[2] = 0x00;
	body[3] = 0x00;
	body[4] = 0x00;

	body[5] = (length >> 24) & 0xff;
	body[6] = (length >> 16) & 0xff;
	body[7] = (length >> 8) & 0xff;
	body[8] = (length) & 0xff;

	/*copy data*/
	memcpy(&body[9], buffer, length);

	packet->m_nTimeStamp = timestamp;
	packet->m_hasAbsTimestamp = 0;
	packet->m_packetType = RTMP_PACKET_TYPE_VIDEO;
	packet->m_nInfoField2 = m_pRtmp->m_stream_id;
	packet->m_nChannel = 0x04;
	packet->m_headerType = RTMP_PACKET_SIZE_MEDIUM;

	if (RTMP_IsConnected(m_pRtmp)) 
	{
		// 呼叫傳送介面
		ret = RTMP_SendPacket(m_pRtmp, packet, TRUE);
		if (ret != 1)
		{
			dm_printf("send_rtmp_video fail");
			ret = -1;
		} 
	} 
	else
	{
		dm_printf("send_rtmp_video RTMP is not ready");
		ret = -1;
	}
	free(packet);
	return ret;
}

6. 初始化rtmp

定義結構體

typedef struct rtmp_infor
{
	char *aac_buf;
	char *x264_buf;
	int nal_len[20];
	int nal_count;
	int audio_first;
	int video_first;
	int init_flag;
	RTMP *prtmp ;
	X264Args x264args;
	AudioEncodeFaac aacargs;
}RTMPInfor;


int RTMP_Send_Init(char *url, int width, int height, int sample_rate, int channel)
{
	int ret = 0;
	if (rtmp_infor.init_flag == 1)
	{
		dm_printf("RTMP_Send_Init again init");
		return -1;
	}
	if (url == NULL)
	{
		dm_printf("url is NULL");
		return -1;
	}
	if (width <= 0 || height <= 0 || channel <= 0)
	{
		dm_printf("width or height or channel is error");
		return -1;
	}
	pthread_mutex_lock(&thread_lock_rtmp_send);
	memset(&rtmp_infor, 0, sizeof(rtmp_infor));
	ret = RTMP_Connect(&rtmp_infor.prtmp, url);
	if (ret < 0)
	{
		dm_printf("RTMP_Connect fail");
		goto end;
	}
	ret = Audio_Encode_Init_Faac(&rtmp_infor.aacargs, sample_rate, channel);
	if (ret < 0)
	{
		dm_printf("Audio_Encode_Init_Faac fail");
		goto end;
	}
	ret = X264encode_Init_Args_ForRtmp(&rtmp_infor.x264args, NULL, width, height);
	if (ret < 0)
	{
		dm_printf("Audio_Encode_Init_Faac fail");
		goto end;
	}
	rtmp_infor.aac_buf = (char *)malloc(NB_SAMPLE << channel);
	rtmp_infor.x264_buf = (char *)malloc(width * height * 3 >> 1);
	if (rtmp_infor.aac_buf == NULL || rtmp_infor.x264_buf == NULL)
	{
		dm_printf("aac_buf or 264_buf alloc fail");
		ret = -1;
		goto end;
	}
	rtmp_infor.init_flag = 1;
end:
	if (ret < 0)
	{
		X264encode_Finish_Args_ForRtmp(&rtmp_infor.x264args);
		Audio_Encode_Release_Faac(&rtmp_infor.aacargs);
		RTMP_Close(&rtmp_infor.prtmp);
		if (rtmp_infor.aac_buf != NULL)
			free(rtmp_infor.aac_buf);
		if (rtmp_infor.x264_buf != NULL)
			free(rtmp_infor.x264_buf);
		memset(&rtmp_infor, 0, sizeof(rtmp_infor));
	}
	pthread_mutex_unlock(&thread_lock_rtmp_send);
	return ret;
}