vlc-添加自定义的demuxer解复用插件----播放h264裸文件

2023-05-16

使用vlc3.0.6  在ubuntu 64bit上编译,vlc使用插件的方式组织对多种视频源的支持,比如 avi、mp4、mkv、等等,这里想添加一个自己的demuxer,从一个h.264文件中读h264数据,播放。(vlc并不支持直接播放h264裸流文件,至少这个v3.0.6版本是没有支持)

一:添加一个demuxer模块:

在moudle/demux 的makefile.am 中添加: 

libwangscr_plugin_la_SOURCES = demux/wang_test/h264src.c 
libwangscr_plugin_la_LIBADD = $(LIBM)
libwangscr_plugin_la_LDFLAGS = $(AM_LDFLAGS)

demux_LTLIBRARIES += libwangscr_plugin.la

然后到源码顶层目录,重新 # ./configure #make

demux/wang_test/h264src.是 自己要添加的插件实现文件

libwangscr 是自己的插件名

最后会得到在 /modules/.libs 目录下得到 libwangscr_plugin.la 

贴上插件代码h264src.c的实现:

            前半部分有从h264文件获取流数据的实现:

#define PLAY_FPS 30  //播放的帧率,可自由设置,(不嫌麻烦可以从h264流的sps中解码出来,让视频正常速度播放)

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include<stdio.h>
#include <vlc_demux.h>
#include <vlc_charset.h>                           /* EnsureUTF8 */
#include <vlc_input.h>
#include <vlc_aout.h>
#include <vlc_plugin.h>


#include <sys/time.h>


#define BUFFER_TIME_MS 500 //缓冲500ms的数据
#define PLAY_FPS 30  //播放的帧率,可自由设置,(不嫌麻烦可以从h264流的sps中解码出来,让视频正常速度播放)
/***

***20190828 canok

*** output: complete frames

**/

#include<stdio.h>
#include<stdlib.h>	
#include <unistd.h>
#include <string.h>
#define MIN(a,b) ((a)<(b)?(a):(b))

typedef unsigned char   uint8_t;     //无符号8位数

#define NALU_TYPE_SLICE 1
#define NALU_TYPE_DPA 2
#define NALU_TYPE_DPB 3
#define NALU_TYPE_DPC 4
#define NALU_TYPE_IDR 5
#define NALU_TYPE_SEI 6
#define NALU_TYPE_SPS 7
#define NALU_TYPE_PPS 8
#define NALU_TYPE_AUD 9
#define NALU_TYPE_EOSEQ 10
#define NALU_TYPE_EOSTREAM 11
#define NALU_TYPE_FILL 12

#define CACH_LEN (1024*200)//缓冲区不能设置太小,如果出现比某一帧比缓冲区大,会被覆盖掉一部分
static uint8_t *g_cach[2] = {NULL,NULL};
static FILE* fp_inH264 = NULL;
static int icach = 0;
static int ioffset = 0;
static int bLoop = 1;
static int init()
{	
	if(g_cach[0] == NULL)
	{
		g_cach[0] = (uint8_t*)malloc(CACH_LEN);
	}
	if(g_cach[1] == NULL)
	{
		g_cach[1] = (uint8_t*)malloc(CACH_LEN);
	}
	
	if(fp_inH264 == NULL)
	{
		fp_inH264 = fopen("./test_move.264","r");
		if(fp_inH264 == NULL)
		{
			printf("fope erro [%d%s]\n",__LINE__,__FUNCTION__);
			return -1;
		}
	}
	
	if(fread(g_cach[icach], 1,CACH_LEN,fp_inH264 )<CACH_LEN)
	{
		printf("intpufile too short [%d%s]\n",__LINE__,__FUNCTION__);
		return -1;
	}
	return 0;
}
static int deinit()
{
	if(g_cach[0])
	{
		free(g_cach[0]);
		g_cach[0] = NULL;
	}
	if(g_cach[1])
	{
		free(g_cach[1]);
		g_cach[1] = NULL;
	}
	
	if(fp_inH264)
	{
		fclose(fp_inH264);
		fp_inH264 = NULL;
	}
	
	
}
static int checkNal(uint8_t nalHeader)
{
	char type = nalHeader & ((1<<5)-1);
	switch(type)
	{
		case NALU_TYPE_SPS:
			printf("sps\n");
			break;
		case NALU_TYPE_PPS:
			printf("pps\n");
			break;
		case NALU_TYPE_IDR:
			printf("I slice !!!!!!!!!!!!!!\n");
			break;
		case NALU_TYPE_SLICE:
			printf("B/P slice\n");
			break;
		case NALU_TYPE_AUD:
			printf("Delimiter==========\n");
			break;
		default:
			printf("type :%d\n",type);
			break;
	}
	return type;
}
static int checkFlag(uint8_t *buffer, int offset) 
{
	static uint8_t mMark[4] = {0x00,0x00,0x00,0x01};
	return !memcmp(buffer+offset,mMark,4);
	//return (!memcmp(buffer+offset,mMark,4) && ((buffer[offset+4]&((1<<5)-1)) == 9) );
}
//获取一个Nal到 buf, bufLen表示缓冲区最大可以容纳的数据
//返回实际的帧数据长度
static int getOneFrame(uint8_t *buf, int bufLen)
{
	int i =0;
	int startpoint = ioffset;
	int endpoint = ioffset;
	for (i = ioffset+4; i <= CACH_LEN - 4; i++) {
		if (checkFlag(g_cach[icach], i)){
			startpoint = ioffset;
			endpoint = i;
			break;
		}
	}
	if(endpoint - startpoint > 0)
	{
		int dataLen = endpoint -startpoint;
		if(bufLen < dataLen)
		{
			printf("recive buffer too short , need %d byte!\n",dataLen);
		}
		memcpy(buf,g_cach[icach]+startpoint, MIN(dataLen,bufLen));
		ioffset = endpoint;
		
		return MIN(dataLen,bufLen);
	}
	else
	{
		int oldLen =CACH_LEN -startpoint;
		memcpy(g_cach[(icach+1)%2],g_cach[icach]+startpoint, oldLen );
		
		int newLen = 0;
		newLen = fread(g_cach[(icach+1)%2]+oldLen, 1,CACH_LEN -(oldLen),fp_inH264);
		if(newLen <CACH_LEN -(oldLen) )
		{
			if(bLoop)
			{
				fseek(fp_inH264,0,SEEK_SET);
				ioffset =0;
				icach =0;
				fread(g_cach[icach], 1,CACH_LEN,fp_inH264 );
				return getOneFrame(buf,bufLen); 
			}
			else
			{
				return -1;
			}
			
		}
		
		ioffset = 0;
		icach = (icach+1)%2;
		
		return getOneFrame(buf,bufLen);
	}
	
}



/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
static int  Open ( vlc_object_t * );
static void Close( vlc_object_t * );


vlc_module_begin ()
    set_category( CAT_INPUT )
    set_subcategory( SUBCAT_INPUT_DEMUX )
    set_description( N_("android src stream demuxer") )
    set_shortname( N_("screen") )
	set_capability( "access_demux", 0 )
    set_callbacks( Open, Close )

vlc_module_end ()

//
static int temp =0;

typedef struct
{
    demux_t         *p_demux;
   
    es_format_t     fmt;
    es_out_id_t     *p_es;
}stream_track_t;

struct demux_sys_t
{
	//记录多路流
	int              i_track;
    stream_track_t     **track;

	int64_t startTimes;
	int count;
	char *buffer;
};
#define DEBUG_INFO 0

static int Demux( demux_t *p_demux )
{
#if 1
	  demux_sys_t    *p_sys = p_demux->p_sys;
	  //在这里获取一帧数据
	  usleep(1000000/PLAY_FPS);
	
	  int len  =0;
	  len  = getOneFrame(p_sys->buffer,CACH_LEN);
	  block_t		 *p_block;
	  
	  if( (p_block = block_Alloc( len )) )
	  {// 填充数据到 block

		struct timeval pts;
		gettimeofday(&pts, NULL);

		int64_t i_pts = (int64_t)pts.tv_sec * INT64_C(1000000) +
			(int64_t)pts.tv_usec;
		
		i_pts &= INT64_C(0x00ffffffffffffff);
		p_block->i_dts =  (i_pts - p_sys->startTimes)+VLC_TS_0;
		p_block->i_pts = p_block->i_dts;

#if DEBUG_INFO
		struct timeval test_time;
		struct tm *st_tm = NULL;
		gettimeofday(&test_time,NULL);
		st_tm = gmtime(&test_time.tv_sec);
		
		printf(" len %08d [%02d:%02d:%02d:%06d] ipts:%ld idts:%ld \n",len,st_tm->tm_hour,st_tm->tm_min,st_tm->tm_sec,test_time.tv_usec,p_block->i_pts,p_block->i_dts);
#endif
		if((p_sys->count++)== (int)(BUFFER_TIME_MS* PLAY_FPS/1000 + 1) )
		{//需要在缓冲区缓冲完后,这里更新一下参考时钟,
		//否则可能出现只解一帧的情况
		//只能手动大致计算下了
			es_out_SetPCR( p_demux->out, p_block->i_dts  );
		}
		memcpy( p_block->p_buffer, p_sys->buffer, len);

	  }
	  //这里只有一个 stream, 发送到track[0] 就行
	  es_out_Send( p_demux->out,p_sys->track[0]->p_es, p_block );
 #endif
	  return VLC_DEMUXER_SUCCESS;

}
static int Control( demux_t *p_demux, int i_query, va_list args )
{
#if DEBUG_INFO
	printf("screen control i_query %#lx [%d%s%s]\n",i_query,__LINE__,__FUNCTION__,__FILE__);
#endif 
	bool *pb;
    int64_t *pi64, i64;
    double  *pf, f;
	
	demux_sys_t *p_sys = p_demux->p_sys;
	switch(i_query)
	{
		case DEMUX_CAN_PAUSE:
        case DEMUX_CAN_SEEK:
			{
				pb = va_arg( args, bool * );
				*pb = false;
				return VLC_SUCCESS;
			}
			break;
		case DEMUX_CAN_CONTROL_PACE:
			{
				pb = va_arg( args, bool * );
				*pb = false;
				 return VLC_SUCCESS;
			}
			break;
		case DEMUX_CAN_CONTROL_RATE:
			{
				pb = va_arg( args, bool * );
				*pb = false  ;
				return VLC_SUCCESS;
			}
			break;
		#if 0
		 case DEMUX_GET_FPS:
            pf = va_arg( args, double * );
            *pf = 30;
            return VLC_SUCCESS;
		#endif
		case DEMUX_GET_PTS_DELAY:
			pi64 = va_arg( args, int64_t * );
			#if 0
			*pi64 = INT64_C(1000)
				  * var_InheritInteger( p_demux, "network-caching" );
			#endif
			*pi64 = INT64_C(1000)*500; 
			return VLC_SUCCESS;
		default:
			return VLC_EGENERIC;
		
	}

}
static int initVideoES(demux_t *p_demux)
{//es_out 添加一个h264 es流
	demux_sys_t *p_sys = p_demux->p_sys;
	
	stream_track_t *tk = (stream_track_t*)malloc( sizeof( stream_track_t ) );
	if(tk ==NULL)
	{
		return -1;
	}
	tk->p_demux     = p_demux;
	es_format_Init( &tk->fmt, VIDEO_ES, VLC_CODEC_H264 );
	 //tk->fmt.video.i_width  = 1920;
     //tk->fmt.video.i_height = 1080;
	tk->p_es = es_out_Add( p_demux->out, &tk->fmt );
	
   if( tk->p_es )
   {
	   TAB_APPEND_CAST( (stream_track_t **), p_sys->i_track, p_sys->track, tk );
   }
   else
   {
	   es_format_Clean( &tk->fmt );
	   free( tk );
	   printf("erro to init VideoEs [%d%s]\n",__LINE__,__FUNCTION__);
	   return -1;
   }

   return init();

}
static int Open( vlc_object_t * p_this )
{
	//printf("wang screen module open ! [%d%s%s]\n",__LINE__,__FUNCTION__,__FILE__);
	demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys = NULL;
	
	p_demux->pf_demux  = Demux;
    p_demux->pf_control= Control;
    p_demux->p_sys     = p_sys = (demux_sys_t*)calloc( 1, sizeof( demux_sys_t ) );
	p_sys->buffer = calloc(1,CACH_LEN);
    if( !p_sys ) return VLC_ENOMEM;
	
	struct timeval pts;
	gettimeofday(&pts, NULL);
	int64_t i_pts = (int64_t)pts.tv_sec * INT64_C(1000000) +
		(int64_t)pts.tv_usec;
	i_pts &= INT64_C(0x00ffffffffffffff);

	p_sys->startTimes = i_pts;
	p_sys->count = 1;
	
	if(initVideoES(p_demux))
	{
		printf("wang screen vedioees init erro![%d%s]\n\n\n",__LINE__,__FUNCTION__);
	}
	//printf("wang screen module open ok! [%d%s%s]\n",__LINE__,__FUNCTION__,__FILE__);


	//important !!!!
	es_out_SetPCR( p_demux->out, VLC_TS_0  );
	return 0;
}

static void Close ( vlc_object_t * p_this )
{
	demux_t *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys = p_demux->p_sys;
	

	for( int i = 0; i < p_sys->i_track; i++ )
    {
        stream_track_t *tk = p_sys->track[i];
        es_format_Clean( &tk->fmt );
        free( tk );
    }
    TAB_CLEAN( p_sys->i_track, p_sys->track );
	
	free(p_sys->buffer);
	free( p_sys );

	deinit();
}

二: 使用vlc库播放:

在 bin/vlc.c main 函数,屏蔽掉源代码,用自己的demo:

int main()
{
    /* The so-called POSIX-compliant MacOS X reportedly processes SIGPIPE even
		 * if it is blocked in all thread.
		 * Note: this is NOT an excuse for not protecting against SIGPIPE. If
		 * LibVLC runs outside of VLC, we cannot rely on this code snippet. */
		signal (SIGPIPE, SIG_IGN);
		/* Restore SIGCHLD in case our parent process ignores it. */
		signal (SIGCHLD, SIG_DFL);
	
	printf("wang [%s:%d:%s] \n",__FILE__,__LINE__,__FUNCTION__);
#ifndef NDEBUG
		/* Activate malloc checking routines to detect heap corruptions. */
		setenv ("MALLOC_CHECK_", "2", 1);
	
		/* Disable the ugly Gnome crash dialog so that we properly segfault */
		setenv ("GNOME_DISABLE_CRASH_DIALOG", "1", 1);
#endif
	
#ifdef TOP_BUILDDIR
		setenv ("VLC_PLUGIN_PATH", TOP_BUILDDIR"/modules", 1);
		setenv ("VLC_DATA_PATH", TOP_SRCDIR"/share", 1);
#endif
	
	/* Clear the X.Org startup notification ID. Otherwise the UI might try to
	 * change the environment while the process is multi-threaded. That could
	 * crash. Screw you X.Org. Next time write a thread-safe specification. */
	unsetenv ("DESKTOP_STARTUP_ID");
//=======================================================//

		libvlc_instance_t *vlc; 
		libvlc_media_player_t *media_player_cli;
		libvlc_media_t *media_cli;
	
		vlc =  libvlc_new(0,NULL);
		if(vlc == NULL)
		{
		   printf("wang erro libvlc_new \n");
		   return -1;
		}
	
		media_player_cli = libvlc_media_player_new(vlc);
		media_cli =  libvlc_media_new_location(vlc,"screen://123");
		
		 libvlc_media_player_set_media(media_player_cli,media_cli);
		 libvlc_media_player_play(media_player_cli);

        while(1); //主线程不能退出,不然子线程也挂掉,播放不了了
}

在libvlc_media_new_location(vlc,"screen://123");这一行代码,"screen" 要和  set_shortname( N_("screen") ) 中的描述,至于123这些没什么用,随便加的。 vlc启动的时候会去插件目录里面扫描所有目录,存到一个树中,上述匹配之后vlc创建demuxer的时候会缓存树里面查找对应库,并加载它作为demuxer使用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

vlc-添加自定义的demuxer解复用插件----播放h264裸文件 的相关文章

  • android mediacodec:实时解码h264 nals

    我正在尝试使用 android 低级媒体 api 实时解码 h264 nals 每个 nal 包含一个完整的帧 所以我希望在用我的 nal 提供输入并调用之后dequeueOutputBuffer它会 立即 当然有一点延迟 显示我的框架 但
  • Android MediaCodec 似乎可以缓冲 H264 帧

    我正在手动读取 RTP H264 流并将 H264 帧传递给 Android MediaCodec 我使用 markerBit 作为框架的边框 MediaCodec 与 OpenGL 纹理 SurfaceTexture 绑定 一般来说 一切
  • 如何在 C# 中通过 VLC api 流式传输视频

    我正在从事视频广播的小型家庭项目 我找到了一些例子Example http csharpmagics blogspot com 但它不起作用 因为需要旧版本的库0 8 6 所以我找到了它 但是当我尝试从 API 获取组件时 我对非托管代码有
  • 从 RTP 流中解码 h264 帧

    我正在使用 live555 和 ffmpeg 库从服务器获取和解码 RTP H264 流 视频流由 ffmpeg 编码 使用 Baseline 配置文件和 x264 param default preset m params veryfas
  • 如何用FFMPEG正确将H264封装成FLV?

    首先 标题中的 适当 指的是这个相关问题 https stackoverflow com questions 44952940 ffmpeg how to wrap h264 stream into flv container 其中的答案并
  • 在Java中启动VLC并通过rc接口连接到它

    我已经看过这个帖子了 但我仍然遇到一个问题 在java中启动vlc播放器 https stackoverflow com questions 1731299 starting vlc player in java看来 VLC 的 Java
  • VLC 语法转码并流式传输到标准输出?

    Goal 我正在尝试使用VLC http www videolan org vlc index html作为本地服务器来扩展使用以下命令创建的应用程序的视频功能Adobe AIR Flex and Actionscript 我在用VLC流式
  • 使用 VLC 托管无限视频循环流

    我想通过 WIFI 网络从带有 VLC 播放器的电脑向智能手机提供视频流以进行回归测试 视频在智能手机上播放完毕后应自动重新开始 我目前使用 rtsp 作为协议和循环选项 但这不是强制性的 问题是 每次视频重新启动时 都需要进行新的 rts
  • 使用 Android MediaCodec 从摄像头编码 H.264

    我正在尝试让它在 Android 4 1 上运行 使用升级的 Asus Transformer 平板电脑 谢谢亚历克斯对我之前问题的回答 https stackoverflow com a 13420558 726156 我已经能够将一些原
  • libvlc - 如何在播放过程中改变音量

    我试图在播放音频文件时设置音量 但它似乎根本不起作用 请问我做错了什么 create a vlc playable object from source self playable vlc libvlc media new path sel
  • 使用 VLC 将文件流式传输为 RTSP

    我需要创建一个可以将 mp3 文件流式传输到另一个设备的服务器 我打算使用 VLC 我查看了 VLC 文档 并对执行此操作的前进方向感到困惑 我找到了这个链接 http www videolan org doc streaming howt
  • C# 嵌入vlc控件

    我尝试将 VLC 嵌入到我的 WPF 项目中 我已经注册了 axvlc dll 还下载了 VLC nightly build 版本 2 2 2 System Windows Markup XamlParseException 类型的第一次机
  • 使用 libavformat API 读取 H264 SPS 和 PPS NAL 字节

    如何使用 libavformat API 读取 H264 SPS 和 PPS NAL 字节 我尝试使用 av read frame input avFormatContext avPkt API 从 mp4 视频 编解码器为 h264 文件
  • Html5 视频和 Flash 方法

    研究 HTML5 视频标签 并研究哪些浏览器支持哪些视频文件类型 我最初的想法是事情变得比仅仅使用 Flash 更困难 我想知道是否有人已经找到一些骨架代码 与视频的开发方法相结合 来执行以下操作 如果闪光灯可用 请使用它 如果没有 请尝试
  • 如何使用 VLC 以 ​​http 方式将视频流式传输到其他计算机 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我想使用以下方式将视频从我的计算机流式传输到另一台计算机http in vlc 我已从此处阅读了如何进行视频流传输的步骤https wik
  • Android版VLC编译错误

    当我根据这个编译适用于Android的VLC时page https wiki videolan org AndroidCompile 在步骤 sh 编译 sh 我收到此错误 For an ARMv6 device without FPU e
  • 将 H.264 I 帧放入 AVSampleBufferDisplayLayer 但不显示视频图像

    在详细回顾了 WWDC2014 Session513 后 我尝试在 IOS8 0 上编写我的应用程序来解码和显示一个实时 H 264 流 首先 我成功构建了H264参数集 当我得到一个带有 4 位起始代码的帧时 就像 0x00 0x00 0
  • 在应用程序启动时禁用 Windows 服务

    因为我必须在应用程序启动时关闭 Windows 高级文本服务 有什么特殊的API吗 它适用于具有默认权限的用户吗 该问题的标题是 禁用 Windows 服务 但答案都告诉我们如何停止服务 您在 Google 上会发现的大部分内容是 您可以使
  • 如何减少 MediaCodec 视频/avc 解码中的延迟

    我执行了一些简单的计时电影播放器 java https github com google grafika blob master src com android grafika MoviePlayer java in the Grafik
  • FFmpeg - H264 编码器找不到有效设备并且无法配置编码器

    我尝试使用 H264 编码器进行编码 但是当我这样做时 出现以下错误 h264 v4l2m2m 0x55682d2416c0 Could not find a valid device h264 v4l2m2m 0x55682d2416c0

随机推荐

  • 理解字节序 大端字节序和小端字节序

    以下内容参考了 http www ruanyifeng com blog 2016 11 byte order html https blog csdn net yishengzhiai005 article details 3967252
  • opencvSharp 学习笔记(二)

    参考文章 xff1a https github com shimat opencvsharp samples tree master SamplesCS Samples 参考opencvsharp的官方sample xff0c 在vs201
  • C++局部对象的析构

    class A span class hljs keyword public span A Func span class hljs attribute span span class hljs attribute span A A spa
  • BIND中基数树的建立

    BIND9新引入了视图的概念 xff0c 简单的来讲就是能根据不同的来源IP来返回不同的数据 其中网段的存储 xff0c 网段的快速匹配都是用基数树来实现的 下面是BIND创建基数树的代码 BIND的IP地址结构 span class hl
  • HTTP协议解析及C/C++代码实现

    超文本传输协议 HTTP 是分布式 协作 超媒体信息系统的应用层协议 这是自 1990 年以来万维网数据通信的基础 HTTP 是一种通用且无状态的协议 xff0c 它可以用于其他目的 xff0c 也可以使用其请求方法 错误代码和标头的扩展
  • C语言发邮件(带账号密码认证),简单的libesmtp实例

    需要安装libesmtp开发环境 xff0c centos下可以用yum安装 yum install libesmtp devel 编译时加上 lesmtp选项 xff0c 账号密码等替换成自己的 gcc o mail mail c les
  • 怎样在Markdown中贴图片

    前言 Markdown真的是一个很优秀的文本标记语言 语法也很简单 熟悉之后基本上可以完全抛弃Word了 用来写文档 一些博客 再好不过了 可是Markdown还是有一个痛点 那就是不大好贴图片 贴图 怎么样在markdown中贴图就不多说
  • 【四】【vlc-android】播放控制交互与demux解复用层、媒体数据流拉取层的具体数据传递和控制流程源码分析

    1 VLC中有很多demux mux encoder decoder模块 xff0c 因此需要先了解这些模块的加载原理 xff0c 模块的加载原理基本一致 xff0c 因此举例分析MP4解复用模块如何加载完成的 xff0c 主要流程如下 x
  • vs2013 设置不显示输出窗口

    工具 选项 项目与解决方案 常规 取消 在生成开始时显示输出窗口 的勾选
  • @Param注解的用法解析

    实例一 64 Param注解单一属性 dao层示例 Public User selectUser 64 param userName String name 64 param userpassword String password xml
  • mybatis choose标签的使用

    有时候我们并不想应用所有的条件 xff0c 而只是想从多个选项中选择一个 而使用if标签时 xff0c 只要test中的表达式为 true xff0c 就会执行 if 标签中的条件 MyBatis 提供了 choose 元素 if标签是与
  • Socket长连接实现思路

    长连接的正确实现方式 1 不关闭流实现长连接 xff1f 流关闭了而不关闭Socket xff0c 还是无法达到长连接的效果的 xff0c 所以 xff0c 要长连接 xff0c 流必须不能关闭 xff01 那么 xff0c 是不是直接不关
  • com.jacob.com.ComFailException: VariantChangeType failed

    调用jacob组件出错 com jacob com ComFailException VariantChangeType failed 在C Windows System32 config systemprofile下创建文件夹Deskto
  • CRC8校验 java实现

    以下为CRC8的实现 span class hljs keyword package span server span class hljs javadoc CRC8相关计算 encode utf 8 span class hljs jav
  • Java list add方法和addAll方法效率

    结论是 在数据量较小时 add方法配合for循环遍历比addAll来得快 但是在大量数据时 addAll的方法的效率更高 list addAll 是浅拷贝 只是将内存中的地址进行了拷贝 指向了原先list的末尾做了拼接
  • STM32——USART1重映射

    前言 为了使不同器件封装的外设 IO 功能数量达到最优 xff0c 可以把一些复用功能重新映射到其他一些引脚上 STM32 中有很多内置外设的输入输出引脚都具有重映射 remap 的功能 我们知道每个内置外设都有若干个输入输出引脚 xff0
  • Pg数据库比较时间大小

    postgresql 比较两个时间差大于 N个小时 摘要 PG 中时间想减后为interval xff0c 比较两个时间大于某个小时或者分钟等可以直接通过interval来实现 example1 xff1a 判断两个时间差大于4个小时 se
  • import java.util.LinkedList; import java.util.Queue; import java.util.Scanner; import java.util.Stac

    span class hljs keyword import span java util LinkedList span class hljs keyword import span java util Queue span class
  • 21-《电子入门趣谈》第四章_自己制作电路板-4.2洞洞板的介绍和经典案例使用教程

    好消息 xff1a 请在手机淘宝或闲鱼上搜索 电子入门趣谈 xff0c 有惊喜哦 我把全本电子入门趣谈的电子版 xff08 包括科技提升和理论升华部分 xff0c 共计50余万字 xff09 放到上面开始兜售啦 xff0c 如果您真的喜欢这
  • vlc-添加自定义的demuxer解复用插件----播放h264裸文件

    使用vlc3 0 6 在ubuntu 64bit上编译 xff0c vlc使用插件的方式组织对多种视频源的支持 xff0c 比如 avi mp4 mkv 等等 xff0c 这里想添加一个自己的demuxer xff0c 从一个h 264文件