rtsp协议的格式与http协议的格式是一样的, 因此可以使用netty的http解析器来处理rtsp交互数据.
netty中自带了一个 RtspDecoder , 但是它几乎没做什么事情, 只是将rtsp消息解析成 HttpRequest , HttpResonse , HttpContent .
因此, 最终还是需要开发者自己处理, 没有什么捷径. 因此本文只是说明netty的基本用法

基本使用方法

    public static void main(String[] args) throws Exception {
         EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1)
         EventLoopGroup workerGroup = new NioEventLoopGroup();
         try {
             ServerBootstrap b = new ServerBootstrap(); // (2)
             b.group(bossGroup, workerGroup)
                     .channel(NioServerSocketChannel.class) // (3)
                     .childHandler(new ChannelInitializer<SocketChannel>() { // (4)
                         @Override
                         public void initChannel(SocketChannel ch) throws Exception {
                             ch.pipeline()
                                      .addLast(new RtspDecoder())   /** 添加netty自带的rtsp消息解析器 */
                                     .addLast(new RTSPHandler())  /** 上一步将消息解析完成之后, 再交给自定义的处理器 */
                                     .addLast(new ReadTimeoutHandler(30));   /** idle超时处理 */
                     .option(ChannelOption.SO_BACKLOG, 128)          // (5)
                     .childOption(ChannelOption.SO_KEEPALIVE, true); // (6)
             ChannelFuture f = b.bind(80).sync(); // (7)
             logger.info("start turn server success");
             f.channel().closeFuture().sync();
         } catch (Exception ex){
             logger.error("start netty failed, ", ex);
         } finally {
             workerGroup.shutdownGracefully();
             bossGroup.shutdownGracefully();

RTSPHandler实现

public class RTSPHandler extends ChannelInboundHandlerAdapter {
	private final static Logger logger = LogManager.getLogger(RTSPHandler.class);
    @Override
    public void channelActive(final ChannelHandlerContext ctx) { // (1)
    	logger.info("channelActive: {}", ctx);
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        logger.info("exceptionCaught: {}", cause);
        ctx.close();
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception{
        logger.info("[RTSPHandler]channelRead:  {}", msg.getClass());
        if(msg instanceof DefaultHttpRequest){
            DefaultHttpRequest req = (DefaultHttpRequest)msg;
            HttpMethod method = req.method();
            String methodName = method.name();
            logger.info("method: {}", methodName);
            /** 以下就是具体消息的处理, 需要开发者自己实现 */
            if(methodName.equalsIgnoreCase("OPTIONS") ||
                    methodName.equalsIgnoreCase("DESCRIBE")){
            }else{
        }else if(msg instanceof HttpContent){
            HttpContent content = (HttpContent)msg;
            if(content.content().isReadable()) {
            		/** 此时, 才表示HttpContent是有内容的, 否则,它是空的, 不需要处理 */

特殊使用方法

既然要用netty来搞rtsp相关的东西, 而不是用live555之类的东西来做, 那肯定是有某些特殊需求. 比如用它来做直播? 视频流转换?

  1. 运行过程中, 动态添加或移除ChannelInboundHandlerAdapter
ctx.channel().pipeline().addLast(upstreamHandler);
ctx_.channel().pipeline().remove(RtspDecoder.class);

如果本handler处理ByteBuf, 发现还有一些数据需要抛给一下handler处理, 可以这样做

        if (buf != null) {
            int readable = buf.readableBytes();
            if (readable > 0) {
                ByteBuf bytes = buf.readBytes(readable);
                buf.release();
                ctx.fireChannelRead(bytes);
            } else {
                buf.release();
            ctx.fireChannelReadComplete();
  1. 将数据抛给下一个handler处理
 @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception{
        /** 发现这个数据不是本handler能处理的, 抛给下一个handler处理 */
        // ....
        ctx.fireChannelRead(msg);
                    rtsp协议的格式与http协议的格式是一样的, 因此可以使用netty的http解析器来处理rtsp交互数据.netty中自带了一个RtspDecoder, 但是它几乎没做什么事情, 只是将rtsp消息解析成HttpRequest,HttpResonse, HttpContent.因此, 最终还是需要开发者自己处理, 没有什么捷径.  因此本文只是说明netty的基本用法基本使用方法  ...
				
本文转自javacv社区三群管理员“赶在时间前面”:过去的过去了的博客,感谢大佬倾情贡献,支持javacv社区发展和壮大。 国标gb28181全系列都可以参考过去的过去了的博客,再次表示感谢。 解析流程参考https://blog.csdn.net/chen495810242/article/details/39207305 代码基于github上的修改https://github.com/yangjiechina/JGB28181 流解析的代码长时间测试海康摄像时还不稳定,所以主要以学习为...
GStreamer是一个流媒体应用程序框架,可以用于音频和视频流的捕获、编码、解码、传输和播放。它支持多种协议,包括RTSP(实时流传输协议),可以用来获取来自网络摄像机或其他支持RTSP协议的设备的视频流。 要从RTSP获取视频流,可以使用GStreamer提供的`rtspsrc`元素。下面是一个简单的GStreamer管道,用于从RTSP获取视频流并将其保存为本地文件: gst-launch-1.0 rtspsrc location=rtsp://example.com/media.mp4 ! decodebin ! autovideosink 其中,`rtspsrc`元素表示从RTSP获取数据,`location`参数指定RTSP流的URL,`decodebin`元素用于解码视频,`autovideosink`元素用于将视频显示在屏幕上。 你也可以使用GStreamer的API来以编程方式实现这一过程。以下是一个使用GStreamer C语言 API实现的示例代码: #include <gst/gst.h> int main(int argc, char *argv[]) { GstElement *pipeline, *source, *decoder, *sink; GstBus *bus; GstMessage *msg; /* Initialize GStreamer */ gst_init(&argc, &argv); /* Create the elements */ source = gst_element_factory_make("rtspsrc", "source"); g_object_set(G_OBJECT(source), "location", "rtsp://example.com/media.mp4", NULL); decoder = gst_element_factory_make("decodebin", "decoder"); sink = gst_element_factory_make("autovideosink", "sink"); /* Create the empty pipeline */ pipeline = gst_pipeline_new("test-pipeline"); if (!pipeline || !source || !decoder || !sink) { g_printerr("Not all elements could be created.\n"); return -1; /* Build the pipeline */ gst_bin_add_many(GST_BIN(pipeline), source, decoder, sink, NULL); if (gst_element_link_many(source, decoder, sink, NULL) != TRUE) { g_printerr("Elements could not be linked.\n"); gst_object_unref(pipeline); return -1; /* Start playing */ gst_element_set_state(pipeline, GST_STATE_PLAYING); /* Wait until error or EOS */ bus = gst_element_get_bus(pipeline); msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS); /* Free resources */ if (msg != NULL) gst_message_unref(msg); gst_object_unref(bus); gst_element_set_state(pipeline, GST_STATE_NULL); gst_object_unref(pipeline); return 0; 这个示例代码使用`gst_element_factory_make()`函数创建了`rtspsrc`、`decodebin`和`autovideosink`元素,并使用`g_object_set()`函数设置了`rtspsrc`元素的`location`属性来指定RTSP流的URL。然后使用`gst_bin_add_many()`函数将这些元素添加到管道中,并使用`gst_element_link_many()`函数将它们链接在一起。最后,使用`gst_element_set_state()`函数将管道设置