ffmpeg 实现RTSP/RTMP 从服务器拉音视频流,保存为h264和AAC

int my_av_bsf_filter(const AVBitStreamFilter *filter, AVPacket *pPacket, const AVCodecParameters *src)
{
	int ret;
	AVBSFContext *ctx = NULL;
	if (!filter)
		return 0;

	ret = av_bsf_alloc(filter, &ctx);
	if (ret < 0)
		return ret;
	ret = avcodec_parameters_copy(ctx->par_in, src);
	if (ret < 0)
		return ret;

	ret = av_bsf_init(ctx);
	if (ret < 0)
		return ret;

	AVPacket pkt = { 0 };
	pkt.data = pPacket->data;
	pkt.size = pPacket->size;

	ret = av_bsf_send_packet(ctx, &pkt);
	if (ret < 0)
		return ret;

	ret = av_bsf_receive_packet(ctx, &pkt);
	if (pkt.data == pPacket->data)//额外处理裸流文件  标准格式 不用往下面走 因为pkt.data没有新的引用。
	{
		uint8_t *poutbuf = (uint8_t*)av_malloc(pkt.size);
		if (!poutbuf) {
			av_packet_unref(&pkt);
			return -1;
		}
		memcpy(poutbuf, pkt.data, pkt.size);
		av_packet_unref(pPacket);
		pPacket->data = poutbuf;
		pPacket->size = pkt.size;
		av_packet_unref(&pkt);
		av_bsf_free(&ctx);
		return 1;
		//av_packet_unref(pPacket);
	}

	if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
		return 0;
	else if (ret < 0)
		return ret;

	// 	uint8_t **poutbuf = &(pPacket->data);
	// 	int *poutbuf_size = &(pPacket->size);

	uint8_t *poutbuf = (uint8_t*)av_malloc(pkt.size + AV_INPUT_BUFFER_PADDING_SIZE);
	if (!poutbuf) {
		av_packet_unref(&pkt);
		return AVERROR(ENOMEM);
	}
	int poutbuf_size = pkt.size;
	memcpy(poutbuf, pkt.data, pkt.size);
	pPacket->data = poutbuf;
	pPacket->size = poutbuf_size;

	av_packet_unref(&pkt);

	/* drain all the remaining packets we cannot return */
	while (ret >= 0) {
		ret = av_bsf_receive_packet(ctx, &pkt);
		av_packet_unref(&pkt);
	}

	av_bsf_free(&ctx);
	return 1;
}

int main(){
        AVFormatContext	*pFormatCtx;
	int				i, videoindex,audioindex;

	AVPacket *packet;
	int ret, got_picture;


	struct SwsContext *img_convert_ctx;
	//下面是公共的RTSP测试地址
//	char filepath[] = "rtsp://184.72.239.149/vod/mp4:BigBuckBunny_115k.mov"; //动画
	char filepath[] = "rtmp://live.hkstv.hk.lxdns.com/live/hks";//香港卫视

	av_register_all();
	avformat_network_init();
	pFormatCtx = avformat_alloc_context();
	//AVDictionary* options = NULL;
	//av_dict_set(&options, "timeout", "10000000", 0);
	if (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) != 0)////打开网络流或文件流
	{
		printf("Couldn't open input stream.\n");
		return -1;
	}
	if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
	{
		printf("Couldn't find stream information.\n");
		return -1;
	}
	videoindex = -1;
	audioindex = -1;
	for (i = 0; i < pFormatCtx->nb_streams; i++) {
		if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
			if (videoindex != -1) {
				continue;
			}
			videoindex = i;
		}
		else if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
			if (audioindex != -1) {
				continue;
			}
			audioindex = i;
		}
		else {
			break;
		}
	}
		
	if (videoindex == -1)
	{
		printf("Didn't find a video stream.\n");
		return -1;
	}

	packet = (AVPacket *)av_malloc(sizeof(AVPacket));

	FILE *fpSave;
	FILE *fpAAcSave;
	if ((fpSave = fopen("geth264.h264", "wb")) == NULL) //h264保存的文件名
		return 0;
	if ((fpAAcSave = fopen("gethAAc.aac", "wb")) == NULL) //h264保存的文件名
		return 0;
	char *padts = (char *)malloc(sizeof(char) * 7);
	int profile = 2;    //AAC LC  
	int freqIdx = 4;  //44.1KHz  
	int chanCfg = 2;
	padts[0] = (char)0xFF; // 11111111     = syncword  
	padts[1] = (char)0xF1; // 1111 1 00 1  = syncword MPEG-2 Layer CRC  
	padts[2] = (char)(((profile - 1) << 6) + (freqIdx << 2) + (chanCfg >> 2));
	padts[6] = (char)0xFC;

	const AVBitStreamFilter *pavBitStFilter = av_bsf_get_by_name("h264_mp4toannexb");
	for (;;)
	{
		//------------------------------
		if (av_read_frame(pFormatCtx, packet) >= 0)
		{
			if (packet->stream_index == videoindex)
			{
				if (my_av_bsf_filter(pavBitStFilter, packet, pFormatCtx->streams[videoindex]->codecpar) != 1)// 添加pps sps(RTMP需要)
				{
					/*len = 0;*/
					return false;
				}
				fwrite(packet->data, 1, packet->size, fpSave);//写数据到文件中

			}
			else if (packet->stream_index == audioindex)// RTMP需要增加AAC的ADTS头(RTSP不用)
			{
				padts[3] = (char)(((chanCfg & 3) << 6) + ((7 + packet->size) >> 11));// 增加ADTS头
				padts[4] = (char)(((7 + packet->size) & 0x7FF) >> 3);
				padts[5] = (char)((((7 + packet->size) & 7) << 5) + 0x1F);
				fwrite(padts, 7, 1, fpAAcSave);
				fwrite(packet->data, 1, packet->size, fpAAcSave);//写数据到文件中
			}
			av_free_packet(packet);
		}
	}

	avformat_close_input(&pFormatCtx);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/venice0708/article/details/80915649