javacv pull up streaming

javacv generally carried out by a frame grabber gripping frame, followed by determination, performs corresponding processing. The following code can handle video frame i and a non-planar frame in a buffer in the left and right channels of audio frames (the vast majority are, including the common recording device)

import java.awt.Image;
import java.nio.ByteBuffer;
import java.nio.ShortBuffer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;
import javax.swing.JFrame;
import org.bytedeco.javacv.CanvasFrame;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;

public class final_VandA {
    public static void main (String[] args) {
         //从rtmp服务器拉流 通过nginx的rtmp模块可迅速简单搭建 单纯的rtmp速度也有3s左右的误差 改为通过websocket传输
    	play("rtmp://192.168.0.1/vod/1.mp4");
    	//流直播
    }
	public static void play(String filepath) {
		Thread playThread = new Thread(new Runnable() { public void run() {
            try {
            	//开始抓取
                @SuppressWarnings("resource")
				final FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(filepath);
                grabber.start();
                //初始化视图
                CanvasFrame canvas = new CanvasFrame("云端",CanvasFrame.getDefaultGamma() / grabber.getGamma());//新建一个窗口
        	    canvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        	    //初始化扬声器
                final AudioFormat audioFormat = new AudioFormat(grabber.getSampleRate(), 16, grabber.getAudioChannels(), true, true);
                final DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
                final SourceDataLine soundLine = (SourceDataLine) AudioSystem.getLine(info);
                soundLine.open(audioFormat);
                soundLine.start();
                //图像转换器 将帧中的image相关信息提取出来
                final Java2DFrameConverter converter = new Java2DFrameConverter();

                ExecutorService executor = Executors.newSingleThreadExecutor();

                while (!Thread.interrupted()) {
                    Frame frame = grabber.grab();
                    if (frame == null) {
                        break;
                    }
                    
                    //帧 为图像帧 或 声音帧
                    if (frame.image != null) {
                    	Image image = converter.convert(frame);
                    	new Runnable() { public void run() {
                            canvas.showImage(image);
                        }}.run();;
                    } else if (frame.samples != null) {
                        final ShortBuffer channelSamplesShortBuffer = (ShortBuffer) frame.samples[0];
                        channelSamplesShortBuffer.rewind();
                        
                        final ByteBuffer outBuffer = ByteBuffer.allocate(channelSamplesShortBuffer.capacity() * 2);

                        for (int i = 0; i < channelSamplesShortBuffer.capacity(); i++) {
                            short val = channelSamplesShortBuffer.get(i);
                            outBuffer.putShort(val);
                        }
                        /*         
                                             * 写入到扬声器
                                             *   并准备下一次读取
                         */
                        try {
                            executor.submit(new Runnable() { public void run() {
                                soundLine.write(outBuffer.array(), 0, outBuffer.capacity());
                                outBuffer.clear();
                            }}).get();
                        } catch (InterruptedException interruptedException) {
                            Thread.currentThread().interrupt();
                        }
                    }
                }
                executor.shutdownNow();
                executor.awaitTermination(10, TimeUnit.SECONDS);
                soundLine.stop();
                grabber.stop();
                grabber.release();
            } catch (Exception exception) {
               
                System.exit(1);
            }
        }});
        playThread.start();
		
	}
}

nginx-rtmp configuration

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}
rtmp{
    server{
        listen 1935;
        chunk_size 4096;
		#点播
        application vod {
            play /tmp/123/video;#点播的地址 例如 在/tmp/123/video目录下有一个1.mp4 从rtmp://ipaddress/vod/1.mp4拉留即可
        }
		#直播rtmp推流转为hls协议拉流 相关配置在http
        application hls {
           live on;
           hls on;
           hls_path /tmp/123/hls;
            hls_fragment 2s;#切片播放的时间长度
            hls_playlist_length 10s;#列表时间的长度
            hls_continuous on; #连续模式。
            hls_cleanup on;    #对多余的切片进行删除。
            hls_nested on;     #嵌套模式
        }
       #直播 rtmp
       application image {
           live on;#单纯的rtmp转发桥接 推流和拉流时使用同一个rtmp地址即可 速度最快
        }
    }
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html;
            index  index.html index.htm;
        }

        
        location /stat {    
            rtmp_stat all;
        rtmp_stat_stylesheet stat.xsl;
    }
 
       location /stat.xsl { 
        root /home/liuyu/下载/nginx-rtmp-module-1.2.1;
    }
	  #hls协议相关转发配置
       location /hls {  #添加视频流存放地址。
        types {
            application/vnd.apple.mpegurl m3u8;
            video/mp2t ts;
        }
        #访问权限开启,否则访问这个地址会报403
        autoindex on;
        alias /tmp/123/hls;#视频流存放地址
        expires -1;
        add_header Cache-Control no-cache;
        #防止跨域问题
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';  
    }
    }
    }

}

hls slow play real-time video, one problem in agreement with ten seconds hls protocol error, with error of the order of seconds rtmp protocol, RTSP millisecond with error, the second is the problem cache module, and may attempt to reduce the buffer reducing the cached plug flow.

Released six original articles · won praise 0 · Views 524

Guess you like

Origin blog.csdn.net/qq_42873492/article/details/104214476