Jitsi和ffplay

时间:2014-06-15 08:37:25

标签: java ffmpeg rtp jitsi

我正在玩jitsi。得到了示例源代码。我修改了一下。 这就是我所拥有的。 我试图在ffplay或任何其他播放器的VLC中播放传输的流, 但我不能。

我使用这些应用程序参数来运行代码:

--local-port-base=5000 --remote-host=localhost --remote-port-base=10000

我做错了什么?

 package com.company;


    /*
     * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
     *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */

import org.jitsi.service.libjitsi.LibJitsi;
import org.jitsi.service.neomedia.*;
import org.jitsi.service.neomedia.device.MediaDevice;
import org.jitsi.service.neomedia.format.MediaFormat;
import org.jitsi.service.neomedia.format.MediaFormatFactory;

import java.io.PrintStream;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;

/**
 * Implements an example application in the fashion of JMF's AVTransmit2 example
 * which demonstrates the use of the <tt>libjitsi</tt> library for the purposes
 * of transmitting audio and video via RTP means.
 *
 * @author Lyubomir Marinov
 */
public class VideoTransmitter {
    /**
     * The port which is the source of the transmission i.e. from which the
     * media is to be transmitted.
     *
     * @see #LOCAL_PORT_BASE_ARG_NAME
     */
    private int localPortBase;

    /**
     * The <tt>MediaStream</tt> instances initialized by this instance indexed
     * by their respective <tt>MediaType</tt> ordinal.
     */
    private MediaStream[] mediaStreams;

    /**
     * The <tt>InetAddress</tt> of the host which is the target of the
     * transmission i.e. to which the media is to be transmitted.
     *
     * @see #REMOTE_HOST_ARG_NAME
     */
    private InetAddress remoteAddr;

    /**
     * The port which is the target of the transmission i.e. to which the media
     * is to be transmitted.
     *
     * @see #REMOTE_PORT_BASE_ARG_NAME
     */
    private int remotePortBase;

    /**
     * Initializes a new <tt>AVTransmit2</tt> instance which is to transmit
     * audio and video to a specific host and a specific port.
     *
     * @param localPortBase  the port which is the source of the transmission
     *                       i.e. from which the media is to be transmitted
     * @param remoteHost     the name of the host which is the target of the
     *                       transmission i.e. to which the media is to be transmitted
     * @param remotePortBase the port which is the target of the transmission
     *                       i.e. to which the media is to be transmitted
     * @throws Exception if any error arises during the parsing of the specified
     *                   <tt>localPortBase</tt>, <tt>remoteHost</tt> and <tt>remotePortBase</tt>
     */
    private VideoTransmitter(
            String localPortBase,
            String remoteHost, String remotePortBase)
            throws Exception {
        this.localPortBase
                = (localPortBase == null)
                ? -1
                : Integer.valueOf(localPortBase).intValue();
        this.remoteAddr = InetAddress.getByName(remoteHost);
        this.remotePortBase = Integer.valueOf(remotePortBase).intValue();
    }

    /**
     * Starts the transmission. Returns null if transmission started ok.
     * Otherwise it returns a string with the reason why the setup failed.
     */
    private String start()
            throws Exception {
        /*
         * Prepare for the start of the transmission i.e. initialize the
         * MediaStream instances.
         */
        MediaType[] mediaTypes = MediaType.values();
        MediaService mediaService = LibJitsi.getMediaService();
        int localPort = localPortBase;
        int remotePort = remotePortBase;

        mediaStreams = new MediaStream[mediaTypes.length];
        for (MediaType mediaType : mediaTypes) {
            if(mediaType != MediaType.VIDEO) continue;
            /*
             * The default MediaDevice (for a specific MediaType) is configured
             * (by the user of the application via some sort of UI) into the
             * ConfigurationService. If there is no ConfigurationService
             * instance known to LibJitsi, the first available MediaDevice of
             * the specified MediaType will be chosen by MediaService.
             */
            MediaDevice device
                    = mediaService.getMediaDeviceForPartialDesktopStreaming(100,100,100,100);
            if (device == null) {
                continue;
            }
            MediaStream mediaStream = mediaService.createMediaStream(device);

            // direction
            /*
             * The AVTransmit2 example sends only and the AVReceive2 receives
             * only. In a call, the MediaStream's direction will most commonly
             * be set to SENDRECV.
             */
            mediaStream.setDirection(MediaDirection.SENDONLY);

            // format
            String encoding;
            double clockRate;
            /*
             * The AVTransmit2 and AVReceive2 examples use the H.264 video
             * codec. Its RTP transmission has no static RTP payload type number
             * assigned.
             */
            byte dynamicRTPPayloadType;

            switch (device.getMediaType()) {
                case AUDIO:
                    encoding = "PCMU";
                    clockRate = 8000;
                /* PCMU has a static RTP payload type number assigned. */
                    dynamicRTPPayloadType = -1;
                    break;
                case VIDEO:
                    encoding = "H264";
                    clockRate = MediaFormatFactory.CLOCK_RATE_NOT_SPECIFIED;
                /*
                 * The dymanic RTP payload type numbers are usually negotiated
                 * in the signaling functionality.
                 */
                    dynamicRTPPayloadType = 99;
                    break;
                default:
                    encoding = null;
                    clockRate = MediaFormatFactory.CLOCK_RATE_NOT_SPECIFIED;
                    dynamicRTPPayloadType = -1;
            }

            if (encoding != null) {
                MediaFormat format
                        = mediaService.getFormatFactory().createMediaFormat(
                        encoding,
                        clockRate);

                /*
                 * The MediaFormat instances which do not have a static RTP
                 * payload type number association must be explicitly assigned
                 * a dynamic RTP payload type number.
                 */
                if (dynamicRTPPayloadType != -1) {
                    mediaStream.addDynamicRTPPayloadType(
                            dynamicRTPPayloadType,
                            format);
                }

                mediaStream.setFormat(format);
            }

            // connector
            StreamConnector connector;

            if (localPortBase == -1) {
                connector = new DefaultStreamConnector();
            } else {
                int localRTPPort = localPort++;
                int localRTCPPort = localPort++;

                connector
                        = new DefaultStreamConnector(
                        new DatagramSocket(localRTPPort),
                        new DatagramSocket(localRTCPPort));
            }
            mediaStream.setConnector(connector);

            // target
            /*
             * The AVTransmit2 and AVReceive2 examples follow the common
             * practice that the RTCP port is right after the RTP port.
             */
            int remoteRTPPort = remotePort++;
            int remoteRTCPPort = remotePort++;

            mediaStream.setTarget(
                    new MediaStreamTarget(
                            new InetSocketAddress(remoteAddr, remoteRTPPort),
                            new InetSocketAddress(remoteAddr, remoteRTCPPort)));

            // name
            /*
             * The name is completely optional and it is not being used by the
             * MediaStream implementation at this time, it is just remembered so
             * that it can be retrieved via MediaStream#getName(). It may be
             * integrated with the signaling functionality if necessary.
             */
            mediaStream.setName(mediaType.toString());

            mediaStreams[mediaType.ordinal()] = mediaStream;
        }

        /*
         * Do start the transmission i.e. start the initialized MediaStream
         * instances.
         */
        for (MediaStream mediaStream : mediaStreams) {
            if (mediaStream != null) {

                mediaStream.start();
            }
        }



        return null;
    }

    /**
     * Stops the transmission if already started
     */
    private void stop() {
        if (mediaStreams != null) {
            for (int i = 0; i < mediaStreams.length; i++) {
                MediaStream mediaStream = mediaStreams[i];

                if (mediaStream != null) {
                    try {
                        mediaStream.stop();
                    } finally {
                        mediaStream.close();
                        mediaStreams[i] = null;
                    }
                }
            }

            mediaStreams = null;
        }
    }

    /**
     * The name of the command-line argument which specifies the port from which
     * the media is to be transmitted. The command-line argument value will be
     * used as the port to transmit the audio RTP from, the next port after it
     * will be to transmit the audio RTCP from. Respectively, the subsequent
     * ports will be used to transmit the video RTP and RTCP from."
     */
    private static final String LOCAL_PORT_BASE_ARG_NAME
            = "--local-port-base=";

    /**
     * The name of the command-line argument which specifies the name of the
     * host to which the media is to be transmitted.
     */
    private static final String REMOTE_HOST_ARG_NAME = "--remote-host=";

    /**
     * The name of the command-line argument which specifies the port to which
     * the media is to be transmitted. The command-line argument value will be
     * used as the port to transmit the audio RTP to, the next port after it
     * will be to transmit the audio RTCP to. Respectively, the subsequent ports
     * will be used to transmit the video RTP and RTCP to."
     */
    private static final String REMOTE_PORT_BASE_ARG_NAME
            = "--remote-port-base=";

    /**
     * The list of command-line arguments accepted as valid by the
     * <tt>AVTransmit2</tt> application along with their human-readable usage
     * descriptions.
     */
    private static final String[][] ARGS
            = {
            {
                    LOCAL_PORT_BASE_ARG_NAME,
                    "The port which is the source of the transmission i.e. from"
                            + " which the media is to be transmitted. The specified"
                            + " value will be used as the port to transmit the audio"
                            + " RTP from, the next port after it will be used to"
                            + " transmit the audio RTCP from. Respectively, the"
                            + " subsequent ports will be used to transmit the video RTP"
                            + " and RTCP from."
            },
            {
                    REMOTE_HOST_ARG_NAME,
                    "The name of the host which is the target of the transmission"
                            + " i.e. to which the media is to be transmitted"
            },
            {
                    REMOTE_PORT_BASE_ARG_NAME,
                    "The port which is the target of the transmission i.e. to which"
                            + " the media is to be transmitted. The specified value"
                            + " will be used as the port to transmit the audio RTP to"
                            + " the next port after it will be used to transmit the"
                            + " audio RTCP to. Respectively, the subsequent ports will"
                            + " be used to transmit the video RTP and RTCP to."
            }
    };

    public static void main(String[] args)
            throws Exception {
        // We need two parameters to do the transmission. For example,
        // ant run-example -Drun.example.name=AVTransmit2 -Drun.example.arg.line="--remote-host=127.0.0.1 --remote-port-base=10000"
        if (args.length < 2) {
            prUsage();
        } else {
            Map<String, String> argMap = parseCommandLineArgs(args);

            LibJitsi.start();
            try {
                // Create a audio transmit object with the specified params.
                VideoTransmitter at
                        = new VideoTransmitter(
                        argMap.get(LOCAL_PORT_BASE_ARG_NAME),
                        argMap.get(REMOTE_HOST_ARG_NAME),
                        argMap.get(REMOTE_PORT_BASE_ARG_NAME));
                // Start the transmission
                String result = at.start();

                // result will be non-null if there was an error. The return
                // value is a String describing the possible error. Print it.
                if (result == null) {
                    System.err.println("Start transmission for 600 seconds...");

                    // Transmit for 60 seconds and then close the processor
                    // This is a safeguard when using a capture data source
                    // so that the capture device will be properly released
                    // before quitting.
                    // The right thing to do would be to have a GUI with a
                    // "Stop" button that would call stop on AVTransmit2
                    try {
                        Thread.sleep(600_000);
                    } catch (InterruptedException ie) {
                    }

                    // Stop the transmission
                    at.stop();

                    System.err.println("...transmission ended.");
                } else {
                    System.err.println("Error : " + result);
                }
            } finally {
                LibJitsi.stop();
            }
        }
    }

    /**
     * Parses the arguments specified to the <tt>AVTransmit2</tt> application on
     * the command line.
     *
     * @param args the arguments specified to the <tt>AVTransmit2</tt>
     *             application on the command line
     * @return a <tt>Map</tt> containing the arguments specified to the
     * <tt>AVTransmit2</tt> application on the command line in the form of
     * name-value associations
     */
    static Map<String, String> parseCommandLineArgs(String[] args) {
        Map<String, String> argMap = new HashMap<String, String>();

        for (String arg : args) {
            int keyEndIndex = arg.indexOf('=');
            String key;
            String value;

            if (keyEndIndex == -1) {
                key = arg;
                value = null;
            } else {
                key = arg.substring(0, keyEndIndex + 1);
                value = arg.substring(keyEndIndex + 1);
            }
            argMap.put(key, value);
        }
        return argMap;
    }

    /**
     * Outputs human-readable description about the usage of the
     * <tt>AVTransmit2</tt> application and the command-line arguments it
     * accepts as valid.
     */
    private static void prUsage() {
        PrintStream err = System.err;

        err.println("Usage: " + VideoTransmitter.class.getName() + " <args>");
        err.println("Valid args:");
        for (String[] arg : ARGS)
            err.println("  " + arg[0] + " " + arg[1]);
    }
    }

0 个答案:

没有答案