Hey Ryo,

First of all, thanks for submitting a patch and for your kind words about
Red5.

We have a dedicated mailing list for Red5 here:
http://osflash.org/mailman/listinfo/red5_osflash.org<http://osflash.org/mailman/listinfo/osflash_osflash.org>Please
sign up for that and send future Red5 emails there. This list that
you sent to is for general Open Source Flash topics.

As for the patch, could you open a ticket on Jira (http://jira.red5.org) and
submit it through there? This way it won't get lost.

Thanks again!

-Chris

On 9/10/07, Ryo Neyama <[EMAIL PROTECTED]> wrote:
>
> Hi,
>
> I'm a user of Red5.  Thank you very much for providing the great open
> source software.
>
> I'm using org.red5.server.stream.ClientBroadcastStream to record video
> stream into flv files.
>
> I expected that calling ClientBroadcastStream#saveAs(name, isAppend)
> multiple times allows me to change the file without any
> frame-overwrapping and any frame-loss.
>
> However, current SVN trunk and v0.6.2 do not behave as I expected. By
> calling saveAs() twice (with different file names), two files are
> created and both files just keep growing.
>
> Calling stopRecording() before second saveAs() works. However, some
> flames seem to be lost.  This seems to be due to unsubscribing from
> the pipe by stopRecording() and skipping some frames before the next
> keyframe.
>
> Subscribing new FileConsumer followed by unsubscribing the original
> FileConsumer results in overwrapping some frames among files.
>
> After some trial and error, I made some changes in the following
> source code in SVN trunk so that I can change files without any
> frame-overwrapping and any frame-loss.  The new code with my patch
> changes files at the next keyframe.
>
>   org.red5.server.stream.ClientBroadcastStream
>   org.red5.server.stream.consumer.FileConsumer
>
> I think this patch might be useful for other users too.  So, I'm
> wondering if this patch could be incorporated into the main stream of
> Red5. Any comments and helps will be appreciated.
>
> Best regards,
> -----------------------------------------
> Ryo Neyama
>   Utagoe Inc.
>   email: [EMAIL PROTECTED]
>   Tel: 03-3461-1118 / Fax: 03-3461-1119
>
>   http://www.utagoe.com/
>   http://channel.is/
> -----------------------------------------
>
> Index:
> C:/work/WorkingDraft/eclipse-ws/red5_server/src/org/red5/server/stream/consumer/FileConsumer.java
> ===================================================================
> ---
> C:/work/WorkingDraft/eclipse-ws/red5_server/src/org/red5/server/stream/consumer/FileConsumer.java
> (revision 2305)
> +++
> C:/work/WorkingDraft/eclipse-ws/red5_server/src/org/red5/server/stream/consumer/FileConsumer.java
> (working copy)
> @@ -44,6 +44,8 @@
> import org.red5.server.messaging.OOBControlMessage;
> import org.red5.server.messaging.PipeConnectionEvent;
> import org.red5.server.net.rtmp.event.IRTMPEvent;
> +import org.red5.server.net.rtmp.event.VideoData;
> +import org.red5.server.net.rtmp.event.VideoData.FrameType;
> import org.red5.server.net.rtmp.message.Constants;
> import org.red5.server.stream.IStreamData;
> import org.red5.server.stream.message.RTMPMessage;
> @@ -87,6 +89,10 @@
>       * Start timestamp
>       */
>         private int startTimestamp;
> +       /**
> +        * Next file
> +        */
> +       private File nextFile;
>
>      /**
>       * Creates file consumer
> @@ -96,10 +102,21 @@
>         public FileConsumer(IScope scope, File file) {
>                 this.scope = scope;
>                 this.file = file;
> +               this.nextFile = null;
>                 offset = 0;
>                 lastTimestamp = 0;
>                 startTimestamp = -1;
>         }
> +
> +       /**
> +        * Changes file
> +        * @param file
> +        */
> +       public synchronized void changeFile(File file) {
> +               if (!file.equals(this.file)) {
> +                       this.nextFile = file;
> +               }
> +       }
>
>      /**
>       * Push message through pipe
> @@ -119,11 +136,21 @@
>                 if (!(message instanceof RTMPMessage)) {
>                         return;
>                 }
> -               if (writer == null) {
> -                       init();
> -               }
>                 RTMPMessage rtmpMsg = (RTMPMessage) message;
>                 final IRTMPEvent msg = rtmpMsg.getBody();
> +               synchronized (this) {
> +                       if (writer == null) {
> +                               init();
> +                       } else if (nextFile != null && msg instanceof
> VideoData && ((VideoData) msg).getFrameType() == FrameType.KEYFRAME) {
> +                               this.file = this.nextFile;
> +                               this.nextFile = null;
> +                               this.writer = null;
> +                               offset = 0;
> +                               lastTimestamp = 0;
> +                               startTimestamp = -1;
> +                               init();
> +                       }
> +               }
>                 if (startTimestamp == -1) {
>                         startTimestamp = msg.getTimestamp();
>                 }
> Index:
> C:/work/WorkingDraft/eclipse-ws/red5_server/src/org/red5/server/stream/ClientBroadcastStream.java
> ===================================================================
> ---
> C:/work/WorkingDraft/eclipse-ws/red5_server/src/org/red5/server/stream/ClientBroadcastStream.java
> (revision 2305)
> +++
> C:/work/WorkingDraft/eclipse-ws/red5_server/src/org/red5/server/stream/ClientBroadcastStream.java
> (working copy)
> @@ -569,15 +569,20 @@
>                 if (log.isDebugEnabled()) {
>                         log.debug("Recording file: " +
> file.getCanonicalPath());
>                 }
> -               recordingFile = new FileConsumer(scope, file);
> -               Map<Object, Object> paramMap = new HashMap<Object,
> Object>();
> -               if (isAppend) {
> -                       paramMap.put("mode", "append");
> +               if (recordingFile == null) {
> +                       recordingFile = new FileConsumer(scope, file);
> +                       Map<Object, Object> paramMap = new HashMap<Object,
> Object>();
> +                       if (isAppend) {
> +                               paramMap.put("mode", "append");
> +                       } else {
> +                               paramMap.put("mode", "record");
> +                       }
> +                       recordPipe.subscribe(recordingFile, paramMap);
> +                       recording = true;
>                 } else {
> -                       paramMap.put("mode", "record");
> +                       recordingFile.changeFile(file);
> +                       recordingFilename = filename;
>                 }
> -               recordPipe.subscribe(recordingFile, paramMap);
> -               recording = true;
>                 recordingFilename = filename;
>         }
>
>
> _______________________________________________
> osflash mailing list
> [EMAIL PROTECTED]
> http://osflash.org/mailman/listinfo/osflash_osflash.org
>
>
_______________________________________________
Red5devs mailing list
[EMAIL PROTECTED]
http://osflash.org/mailman/listinfo/red5devs_osflash.org
_______________________________________________
Red5 mailing list
Red5@osflash.org
http://osflash.org/mailman/listinfo/red5_osflash.org

Reply via email to