Search in sources :

Example 1 with IStreamCodecInfo

use of org.red5.codec.IStreamCodecInfo in project red5-server-common by Red5.

the class ClientBroadcastStream method dispatchEvent.

/**
 * Dispatches event
 *
 * @param event
 *            Event to dispatch
 */
public void dispatchEvent(IEvent event) {
    if (event instanceof IRTMPEvent && !closed.get()) {
        switch(event.getType()) {
            case STREAM_CONTROL:
            case STREAM_DATA:
                // create the event
                IRTMPEvent rtmpEvent;
                try {
                    rtmpEvent = (IRTMPEvent) event;
                } catch (ClassCastException e) {
                    log.error("Class cast exception in event dispatch", e);
                    return;
                }
                int eventTime = rtmpEvent.getTimestamp();
                // verify and / or set source type
                if (rtmpEvent.getSourceType() != Constants.SOURCE_TYPE_LIVE) {
                    rtmpEvent.setSourceType(Constants.SOURCE_TYPE_LIVE);
                }
                /*
                     * if (log.isTraceEnabled()) { // If this is first packet save its timestamp; expect it is // absolute? no matter: it's never used! if (firstPacketTime == -1) { firstPacketTime =
                     * rtmpEvent.getTimestamp(); log.trace(String.format("CBS=@%08x: rtmpEvent=%s creation=%s firstPacketTime=%d", System.identityHashCode(this), rtmpEvent.getClass().getSimpleName(),
                     * creationTime, firstPacketTime)); } else { log.trace(String.format("CBS=@%08x: rtmpEvent=%s creation=%s firstPacketTime=%d timestamp=%d", System.identityHashCode(this),
                     * rtmpEvent.getClass().getSimpleName(), creationTime, firstPacketTime, eventTime)); } }
                     */
                // get the buffer only once per call
                IoBuffer buf = null;
                if (rtmpEvent instanceof IStreamData && (buf = ((IStreamData<?>) rtmpEvent).getData()) != null) {
                    bytesReceived += buf.limit();
                }
                // get stream codec
                IStreamCodecInfo codecInfo = getCodecInfo();
                StreamCodecInfo info = null;
                if (codecInfo instanceof StreamCodecInfo) {
                    info = (StreamCodecInfo) codecInfo;
                }
                // log.trace("Stream codec info: {}", info);
                if (rtmpEvent instanceof AudioData) {
                    // log.trace("Audio: {}", eventTime);
                    IAudioStreamCodec audioStreamCodec = null;
                    if (checkAudioCodec) {
                        // dont try to read codec info from 0 length audio packets
                        if (buf.limit() > 0) {
                            audioStreamCodec = AudioCodecFactory.getAudioCodec(buf);
                            if (info != null) {
                                info.setAudioCodec(audioStreamCodec);
                            }
                            checkAudioCodec = false;
                        }
                    } else if (codecInfo != null) {
                        audioStreamCodec = codecInfo.getAudioCodec();
                    }
                    if (audioStreamCodec != null) {
                        audioStreamCodec.addData(buf);
                    }
                    if (info != null) {
                        info.setHasAudio(true);
                    }
                } else if (rtmpEvent instanceof VideoData) {
                    // log.trace("Video: {}", eventTime);
                    IVideoStreamCodec videoStreamCodec = null;
                    if (checkVideoCodec) {
                        videoStreamCodec = VideoCodecFactory.getVideoCodec(buf);
                        if (info != null) {
                            info.setVideoCodec(videoStreamCodec);
                        }
                        checkVideoCodec = false;
                    } else if (codecInfo != null) {
                        videoStreamCodec = codecInfo.getVideoCodec();
                    }
                    if (videoStreamCodec != null) {
                        videoStreamCodec.addData(buf, eventTime);
                    }
                    if (info != null) {
                        info.setHasVideo(true);
                    }
                } else if (rtmpEvent instanceof Invoke) {
                    // event / stream listeners will not be notified of invokes
                    return;
                } else if (rtmpEvent instanceof Notify) {
                    Notify notifyEvent = (Notify) rtmpEvent;
                    String action = notifyEvent.getAction();
                    // }
                    if ("onMetaData".equals(action)) {
                        // store the metadata
                        try {
                            // log.debug("Setting metadata");
                            setMetaData(notifyEvent.duplicate());
                        } catch (Exception e) {
                            log.warn("Metadata could not be duplicated for this stream", e);
                        }
                    }
                }
                // update last event time
                if (eventTime > latestTimeStamp) {
                    latestTimeStamp = eventTime;
                }
                // notify event listeners
                checkSendNotifications(event);
                // note this timestamp is set in event/body but not in the associated header
                try {
                    // route to live
                    if (livePipe != null) {
                        // create new RTMP message, initialize it and push through pipe
                        RTMPMessage msg = RTMPMessage.build(rtmpEvent, eventTime);
                        livePipe.pushMessage(msg);
                    } else if (log.isDebugEnabled()) {
                        log.debug("Live pipe was null, message was not pushed");
                    }
                } catch (IOException err) {
                    stop();
                }
                // notify listeners about received packet
                if (rtmpEvent instanceof IStreamPacket) {
                    for (IStreamListener listener : getStreamListeners()) {
                        try {
                            listener.packetReceived(this, (IStreamPacket) rtmpEvent);
                        } catch (Exception e) {
                            log.error("Error while notifying listener {}", listener, e);
                            if (listener instanceof RecordingListener) {
                                sendRecordFailedNotify(e.getMessage());
                            }
                        }
                    }
                }
                break;
            default:
        }
    } else {
        log.debug("Event was of wrong type or stream is closed ({})", closed);
    }
}
Also used : IStreamListener(org.red5.server.api.stream.IStreamListener) AudioData(org.red5.server.net.rtmp.event.AudioData) Notify(org.red5.server.net.rtmp.event.Notify) IRTMPEvent(org.red5.server.net.rtmp.event.IRTMPEvent) IOException(java.io.IOException) IStreamCodecInfo(org.red5.codec.IStreamCodecInfo) StreamCodecInfo(org.red5.codec.StreamCodecInfo) IVideoStreamCodec(org.red5.codec.IVideoStreamCodec) InstanceAlreadyExistsException(javax.management.InstanceAlreadyExistsException) IOException(java.io.IOException) IoBuffer(org.apache.mina.core.buffer.IoBuffer) IAudioStreamCodec(org.red5.codec.IAudioStreamCodec) Invoke(org.red5.server.net.rtmp.event.Invoke) RTMPMessage(org.red5.server.stream.message.RTMPMessage) VideoData(org.red5.server.net.rtmp.event.VideoData) IStreamCodecInfo(org.red5.codec.IStreamCodecInfo) IStreamPacket(org.red5.server.api.stream.IStreamPacket)

Example 2 with IStreamCodecInfo

use of org.red5.codec.IStreamCodecInfo in project red5-server-common by Red5.

the class PlayEngine method playLive.

/**
 * Performs the processes needed for live streams. The following items are sent if they exist:
 * <ul>
 * <li>Metadata</li>
 * <li>Decoder configurations (ie. AVC codec)</li>
 * <li>Most recent keyframe</li>
 * </ul>
 *
 * @throws IOException
 */
private final void playLive() throws IOException {
    // change state
    subscriberStream.setState(StreamState.PLAYING);
    IMessageInput in = msgInReference.get();
    IMessageOutput out = msgOutReference.get();
    if (in != null && out != null) {
        // get the stream so that we can grab any metadata and decoder configs
        IBroadcastStream stream = (IBroadcastStream) ((IBroadcastScope) in).getClientBroadcastStream();
        // prevent an NPE when a play list is created and then immediately flushed
        int ts = 0;
        if (stream != null) {
            Notify metaData = stream.getMetaData();
            // check for metadata to send
            if (metaData != null) {
                ts = metaData.getTimestamp();
                log.debug("Metadata is available");
                RTMPMessage metaMsg = RTMPMessage.build(metaData, metaData.getTimestamp());
                sendMessage(metaMsg);
            } else {
                log.debug("No metadata available");
            }
            IStreamCodecInfo codecInfo = stream.getCodecInfo();
            log.debug("Codec info: {}", codecInfo);
            if (codecInfo instanceof StreamCodecInfo) {
                StreamCodecInfo info = (StreamCodecInfo) codecInfo;
                // handle video codec with configuration
                IVideoStreamCodec videoCodec = info.getVideoCodec();
                log.debug("Video codec: {}", videoCodec);
                if (videoCodec != null) {
                    // check for decoder configuration to send
                    IoBuffer config = videoCodec.getDecoderConfiguration();
                    if (config != null) {
                        log.debug("Decoder configuration is available for {}", videoCodec.getName());
                        VideoData conf = new VideoData(config, true);
                        log.debug("Pushing video decoder configuration");
                        sendMessage(RTMPMessage.build(conf, ts));
                    }
                    // check for keyframes to send
                    FrameData[] keyFrames = videoCodec.getKeyframes();
                    for (FrameData keyframe : keyFrames) {
                        log.debug("Keyframe is available");
                        VideoData video = new VideoData(keyframe.getFrame(), true);
                        log.debug("Pushing keyframe");
                        sendMessage(RTMPMessage.build(video, ts));
                    }
                } else {
                    log.debug("No video decoder configuration available");
                }
                // handle audio codec with configuration
                IAudioStreamCodec audioCodec = info.getAudioCodec();
                log.debug("Audio codec: {}", audioCodec);
                if (audioCodec != null) {
                    // check for decoder configuration to send
                    IoBuffer config = audioCodec.getDecoderConfiguration();
                    if (config != null) {
                        log.debug("Decoder configuration is available for {}", audioCodec.getName());
                        AudioData conf = new AudioData(config.asReadOnlyBuffer());
                        log.debug("Pushing audio decoder configuration");
                        sendMessage(RTMPMessage.build(conf, ts));
                    }
                } else {
                    log.debug("No audio decoder configuration available");
                }
            }
        }
    } else {
        throw new IOException(String.format("A message pipe is null - in: %b out: %b", (msgInReference == null), (msgOutReference == null)));
    }
    configsDone = true;
}
Also used : AudioData(org.red5.server.net.rtmp.event.AudioData) Notify(org.red5.server.net.rtmp.event.Notify) IMessageInput(org.red5.server.messaging.IMessageInput) IOException(java.io.IOException) IStreamCodecInfo(org.red5.codec.IStreamCodecInfo) StreamCodecInfo(org.red5.codec.StreamCodecInfo) IVideoStreamCodec(org.red5.codec.IVideoStreamCodec) IoBuffer(org.apache.mina.core.buffer.IoBuffer) IAudioStreamCodec(org.red5.codec.IAudioStreamCodec) IBroadcastStream(org.red5.server.api.stream.IBroadcastStream) RTMPMessage(org.red5.server.stream.message.RTMPMessage) IMessageOutput(org.red5.server.messaging.IMessageOutput) VideoData(org.red5.server.net.rtmp.event.VideoData) IStreamCodecInfo(org.red5.codec.IStreamCodecInfo) FrameData(org.red5.codec.IVideoStreamCodec.FrameData)

Example 3 with IStreamCodecInfo

use of org.red5.codec.IStreamCodecInfo in project red5-server by Red5.

the class ServerStream method saveAs.

/**
 * {@inheritDoc}
 */
public void saveAs(String name, boolean isAppend) throws IOException {
    // one recording listener at a time via this entry point
    if (recordingListener == null) {
        IScope scope = getScope();
        // create a recording listener
        IRecordingListener listener = (IRecordingListener) ScopeUtils.getScopeService(scope, IRecordingListener.class, RecordingListener.class);
        // initialize the listener
        if (listener.init(scope, name, isAppend)) {
            // get decoder info if it exists for the stream
            IStreamCodecInfo codecInfo = getCodecInfo();
            log.debug("Codec info: {}", codecInfo);
            if (codecInfo instanceof StreamCodecInfo) {
                StreamCodecInfo info = (StreamCodecInfo) codecInfo;
                IVideoStreamCodec videoCodec = info.getVideoCodec();
                log.debug("Video codec: {}", videoCodec);
                if (videoCodec != null) {
                    // check for decoder configuration to send
                    IoBuffer config = videoCodec.getDecoderConfiguration();
                    if (config != null) {
                        log.debug("Decoder configuration is available for {}", videoCodec.getName());
                        VideoData videoConf = new VideoData(config.asReadOnlyBuffer());
                        try {
                            log.debug("Setting decoder configuration for recording");
                            listener.getFileConsumer().setVideoDecoderConfiguration(videoConf);
                        } finally {
                            videoConf.release();
                        }
                    }
                } else {
                    log.debug("Could not initialize stream output, videoCodec is null.");
                }
                IAudioStreamCodec audioCodec = info.getAudioCodec();
                log.debug("Audio codec: {}", audioCodec);
                if (audioCodec != null) {
                    // check for decoder configuration to send
                    IoBuffer config = audioCodec.getDecoderConfiguration();
                    if (config != null) {
                        log.debug("Decoder configuration is available for {}", audioCodec.getName());
                        AudioData audioConf = new AudioData(config.asReadOnlyBuffer());
                        try {
                            log.debug("Setting decoder configuration for recording");
                            listener.getFileConsumer().setAudioDecoderConfiguration(audioConf);
                        } finally {
                            audioConf.release();
                        }
                    }
                } else {
                    log.debug("No decoder configuration available, audioCodec is null.");
                }
            }
            // set as primary listener
            recordingListener = new WeakReference<>(listener);
            // add as a listener
            addStreamListener(listener);
            // start the listener thread
            listener.start();
        } else {
            log.warn("Recording listener failed to initialize for stream: {}", name);
        }
    } else {
        log.info("Recording listener already exists for stream: {}", name);
    }
}
Also used : AudioData(org.red5.server.net.rtmp.event.AudioData) VideoData(org.red5.server.net.rtmp.event.VideoData) IScope(org.red5.server.api.scope.IScope) IStreamCodecInfo(org.red5.codec.IStreamCodecInfo) IStreamCodecInfo(org.red5.codec.IStreamCodecInfo) StreamCodecInfo(org.red5.codec.StreamCodecInfo) IVideoStreamCodec(org.red5.codec.IVideoStreamCodec) IoBuffer(org.apache.mina.core.buffer.IoBuffer) IAudioStreamCodec(org.red5.codec.IAudioStreamCodec)

Example 4 with IStreamCodecInfo

use of org.red5.codec.IStreamCodecInfo in project red5-server-common by Red5.

the class ClientBroadcastStream method saveAs.

/**
 * Save broadcasted stream.
 *
 * @param name
 *            Stream name
 * @param isAppend
 *            Append mode
 * @throws IOException
 *             File could not be created/written to
 */
public void saveAs(String name, boolean isAppend) throws IOException {
    // log.debug("SaveAs - name: {} append: {}", name, isAppend);
    // get connection to check if client is still streaming
    IStreamCapableConnection conn = getConnection();
    if (conn == null) {
        throw new IOException("Stream is no longer connected");
    }
    // one recording listener at a time via this entry point
    if (recordingListener == null) {
        // XXX Paul: Revisit this section to allow for implementation of custom IRecordingListener
        // IRecordingListener listener = (IRecordingListener) ScopeUtils.getScopeService(conn.getScope(), IRecordingListener.class, RecordingListener.class, false);
        // create a recording listener
        IRecordingListener listener = new RecordingListener();
        // initialize the listener
        if (listener.init(conn, name, isAppend)) {
            // get decoder info if it exists for the stream
            IStreamCodecInfo codecInfo = getCodecInfo();
            // log.debug("Codec info: {}", codecInfo);
            if (codecInfo instanceof StreamCodecInfo) {
                StreamCodecInfo info = (StreamCodecInfo) codecInfo;
                IVideoStreamCodec videoCodec = info.getVideoCodec();
                // log.debug("Video codec: {}", videoCodec);
                if (videoCodec != null) {
                    // check for decoder configuration to send
                    IoBuffer config = videoCodec.getDecoderConfiguration();
                    if (config != null) {
                        // log.debug("Decoder configuration is available for {}", videoCodec.getName());
                        VideoData videoConf = new VideoData(config.asReadOnlyBuffer());
                        try {
                            // log.debug("Setting decoder configuration for recording");
                            listener.getFileConsumer().setVideoDecoderConfiguration(videoConf);
                        } finally {
                            videoConf.release();
                        }
                    }
                } else {
                    log.debug("Could not initialize stream output, videoCodec is null.");
                }
                IAudioStreamCodec audioCodec = info.getAudioCodec();
                // log.debug("Audio codec: {}", audioCodec);
                if (audioCodec != null) {
                    // check for decoder configuration to send
                    IoBuffer config = audioCodec.getDecoderConfiguration();
                    if (config != null) {
                        // log.debug("Decoder configuration is available for {}", audioCodec.getName());
                        AudioData audioConf = new AudioData(config.asReadOnlyBuffer());
                        try {
                            // log.debug("Setting decoder configuration for recording");
                            listener.getFileConsumer().setAudioDecoderConfiguration(audioConf);
                        } finally {
                            audioConf.release();
                        }
                    }
                } else {
                    log.debug("No decoder configuration available, audioCodec is null.");
                }
            }
            // set as primary listener
            recordingListener = new WeakReference<IRecordingListener>(listener);
            // add as a listener
            addStreamListener(listener);
            // start the listener thread
            listener.start();
        } else {
            log.warn("Recording listener failed to initialize for stream: {}", name);
        }
    } else {
        log.debug("Recording listener already exists for stream: {} auto record enabled: {}", name, automaticRecording);
    }
}
Also used : AudioData(org.red5.server.net.rtmp.event.AudioData) VideoData(org.red5.server.net.rtmp.event.VideoData) IStreamCodecInfo(org.red5.codec.IStreamCodecInfo) IOException(java.io.IOException) IStreamCodecInfo(org.red5.codec.IStreamCodecInfo) StreamCodecInfo(org.red5.codec.StreamCodecInfo) IVideoStreamCodec(org.red5.codec.IVideoStreamCodec) IStreamCapableConnection(org.red5.server.api.stream.IStreamCapableConnection) IoBuffer(org.apache.mina.core.buffer.IoBuffer) IAudioStreamCodec(org.red5.codec.IAudioStreamCodec)

Aggregations

IoBuffer (org.apache.mina.core.buffer.IoBuffer)4 IAudioStreamCodec (org.red5.codec.IAudioStreamCodec)4 IStreamCodecInfo (org.red5.codec.IStreamCodecInfo)4 IVideoStreamCodec (org.red5.codec.IVideoStreamCodec)4 StreamCodecInfo (org.red5.codec.StreamCodecInfo)4 AudioData (org.red5.server.net.rtmp.event.AudioData)4 VideoData (org.red5.server.net.rtmp.event.VideoData)4 IOException (java.io.IOException)3 Notify (org.red5.server.net.rtmp.event.Notify)2 RTMPMessage (org.red5.server.stream.message.RTMPMessage)2 InstanceAlreadyExistsException (javax.management.InstanceAlreadyExistsException)1 FrameData (org.red5.codec.IVideoStreamCodec.FrameData)1 IScope (org.red5.server.api.scope.IScope)1 IBroadcastStream (org.red5.server.api.stream.IBroadcastStream)1 IStreamCapableConnection (org.red5.server.api.stream.IStreamCapableConnection)1 IStreamListener (org.red5.server.api.stream.IStreamListener)1 IStreamPacket (org.red5.server.api.stream.IStreamPacket)1 IMessageInput (org.red5.server.messaging.IMessageInput)1 IMessageOutput (org.red5.server.messaging.IMessageOutput)1 IRTMPEvent (org.red5.server.net.rtmp.event.IRTMPEvent)1