kearygriffin / streambaby

Automatically exported from code.google.com/p/streambaby
1 stars 0 forks source link

Can the mod_h264_streaming port used in this project be used standalone? #25

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
This is more a question than an issue: I have been looking for a Java port of 
mod_h264_streaming 
for quite some time and have not found anything solid and lightweight. 
Therefore I am wondering 
whether the port in streambaby can be used standalone, i.e., whether the code 
can be used to 
stream H264 movies to for instance a FlowPlayer in a browser with HTTP 
pseudo-streaming 
support?

I am very much willing to contribute but would like to ask first whether you 
think this is easily 
possible. I do not know TiVo.

Also, the goal is not to stream arbitrary videos; it is ok for me if they need 
to be encoded in some 
particular way (bandwidth limitations, etc.)

Original issue reported on code.google.com by kaspar.f...@gmail.com on 30 Sep 2009 at 7:45

GoogleCodeExporter commented 9 years ago
Shouldn't be a problem-- It was designed to work outside streambaby. (although I
haven't tried it in a while...)

There are actually two main classes (both of which require several support 
classes):  
JavaMP4Splitter
CPortMP4Splitter

Both classes inherit from InputStream so once you create an object from them you
simply treat it as an open MP4 stream.

CPortMP4Splitter is based on the original port of mod_h264_streaming.  This was 
the
original code Streambaby used.  There were some small issues however, and the 
code
was hard to maintain because it was a straight-C port without much 
understanding.

JavaMP4Splitter is what is currently used and is was based on straight Java code
written by Cahoon:  http://code.google.com/p/mp4splitter/  It may be a better 
bet. 
It will require (at a minimum the following support classes): MP4Streamer and
mp4.util.*.  It may require a few other support classes, but without trying to 
break
it out myself I'm not sure what they may be, and I think they hopefully just a 
couple
standalone classes.

It may be better to discuss this on the main streambaby support thread over at
tivocommunity:
http://tivocommunity.com/tivo-vb/showthread.php?t=416858

Original comment by kearygri...@gmail.com on 30 Sep 2009 at 10:16

GoogleCodeExporter commented 9 years ago
Thanks a lot for your very valuable feedback. I have followed your suggestions 
and played around with 
JavaMP4Splitter. As you said, only a few support classes are needed. I have, 
however, run into a conceptual 
problem and also have an administrative question.

Let's start with the latter. I think it would be nice if streambaby provided 
the H264 HTTP Pseudo-Streaming 
feature out-of-the-box, without me hacking something together based on a 
checkout of your current code - 
which will not benefit from any changes you make to the project. I see two ways 
to achieve this: Either we 
slightly adapt the code in the streambaby repository so that one can simply use 
the streambaby JAR, or I set 
up a new project on Google Code that uses SVN externals in appropriate 
subdirectories of the project to 
include the necessary Java files from your repository. What is your opinion?

In any case, I think the following change is needed: JavaMP4Splitter.java, 
NamedStream.java, and 
SocketProcessInputStream.java have a tight dependency on 
com.unwiredappeal.tivo.utils.Log. If one (like me) 
does not want to use this particular logging mechanism, you have a problem. One 
way out would be to 
convert Log.java to an interface and add a setter setLog(Log) to these classes. 
Not so nice but it allows for 
injection. Maybe you see another way?

The second question is technical: I see that the JavaMP4Splitter.Splitter class 
creates a new thread and after a 
first glimpse this looks like some producer-consumer pattern. When I use 
JavaMP4Splitter to deliver a file via 
Jersey REST Web Service, I run into IOExceptions thrown by the 

  out.write(input, 0, read);

call in MdatAtom's 

  public void writeData(DataOutput out) throws IOException

method. A closer inspection shows that the PipedInputStream is closed (closed 
by reader). I am not sure 
whether this is due to a bug in my code but more importantly, I am not sure 
whether starting a new thread is 
a good idea/necessary at all in my setting. Do you see clearer here? Could one 
add an option to disable the 
creation of the thread?

I see in your code,

          final PipedOutputStream po = new PipedOutputStream(pi);
          // writeSplitMp4(new DataOutputStream(po));
          (new Thread()
          {

            @Override
            public void run()
            {
              try
              {
                writeSplitMp4(new DataOutputStream(po));
                po.close();
              }
              catch (IOException e)
              {
                Log.error("IOException: " + e);
                try
                {
                  po.close();
                }
                catch (IOException e1)
                {
                }
              }
            }
          }).start();

that you once tried it without the thread but uncommenting this and commenting 
out the thread creation 
blocks for me.

Best,
Kaspar

P.S. My project is a Maven project and thus relatively easy to use; let me know 
if you need it already now.

P.P.S. By the way: the following files are needed:

com/unwiredappeal/mediastreams/mp4/JavaMP4Splitter.java
com/unwiredappeal/mediastreams/mp4/MP4Streamer.java
#com/unwiredappeal/mediastreams/mp4/StreamableMP4.java
com/unwiredappeal/sample/rest/MovieRestService.java
com/unwiredappeal/tivo/utils/AccessibleByteArrayOutputStream.java
com/unwiredappeal/tivo/utils/AvailableSocket.java
com/unwiredappeal/tivo/utils/BitInputStream.java
com/unwiredappeal/tivo/utils/EasySSLHelper.java
com/unwiredappeal/tivo/utils/Log.java
com/unwiredappeal/tivo/utils/NamedStream.java
com/unwiredappeal/tivo/utils/Persistent.java
com/unwiredappeal/tivo/utils/PersistentHashTable.java
com/unwiredappeal/tivo/utils/PropertyReplacer.java
com/unwiredappeal/tivo/utils/RandomAccessFileInputStream.java
com/unwiredappeal/tivo/utils/RandomAccessInputStream.java
com/unwiredappeal/tivo/utils/SimpleCookieManager.java
com/unwiredappeal/tivo/utils/SocketProcessInputStream.java
com/unwiredappeal/tivo/utils/TempFileManager.java
com/unwiredappeal/tivo/utils/Utils.java
com/unwiredappeal/tivo/utils/WordWrap.java
mp4/util/atom/AppleMetaAtom.java
mp4/util/atom/Atom.java
mp4/util/atom/AtomError.java
mp4/util/atom/AtomException.java
mp4/util/atom/AtomVisitor.java
mp4/util/atom/Avc1Atom.java
mp4/util/atom/AvcCAtom.java
mp4/util/atom/ByteStream.java
mp4/util/atom/CdscAtom.java
mp4/util/atom/ChapAtom.java
mp4/util/atom/Co64Atom.java
mp4/util/atom/ContainerAtom.java
mp4/util/atom/CttsAtom.java
mp4/util/atom/DataAtom.java
mp4/util/atom/DefaultAtomVisitor.java
mp4/util/atom/DinfAtom.java
mp4/util/atom/DrefAtom.java
mp4/util/atom/EdtsAtom.java
mp4/util/atom/ElstAtom.java
mp4/util/atom/FreeAtom.java
mp4/util/atom/FtypAtom.java
mp4/util/atom/GmhdAtom.java
mp4/util/atom/HdlrAtom.java
mp4/util/atom/HintAtom.java
mp4/util/atom/HybridAtom.java
mp4/util/atom/IMhdAtom.java
mp4/util/atom/IodsAtom.java
mp4/util/atom/ITrefTypeAtom.java
mp4/util/atom/LeafAtom.java
mp4/util/atom/MdatAtom.java
mp4/util/atom/MdhdAtom.java
mp4/util/atom/MdiaAtom.java
mp4/util/atom/MinfAtom.java
mp4/util/atom/moov/udta/meta/ilst/AARTAtom.java
mp4/util/atom/moov/udta/meta/ilst/CatgAtom.java
mp4/util/atom/moov/udta/meta/ilst/CovrAtom.java
mp4/util/atom/moov/udta/meta/ilst/CpilAtom.java
mp4/util/atom/moov/udta/meta/ilst/CprtalbAtom.java
mp4/util/atom/moov/udta/meta/ilst/CprtartAtom.java
mp4/util/atom/moov/udta/meta/ilst/CprtAtom.java
mp4/util/atom/moov/udta/meta/ilst/CprtcmtAtom.java
mp4/util/atom/moov/udta/meta/ilst/CprtdayAtom.java
mp4/util/atom/moov/udta/meta/ilst/CprtgenAtom.java
mp4/util/atom/moov/udta/meta/ilst/CprtgrpAtom.java
mp4/util/atom/moov/udta/meta/ilst/CprtlyrAtom.java
mp4/util/atom/moov/udta/meta/ilst/CprtnamAtom.java
mp4/util/atom/moov/udta/meta/ilst/CprttooAtom.java
mp4/util/atom/moov/udta/meta/ilst/CprtwrtAtom.java
mp4/util/atom/moov/udta/meta/ilst/DescAtom.java
mp4/util/atom/moov/udta/meta/ilst/DiskAtom.java
mp4/util/atom/moov/udta/meta/ilst/EgidAtom.java
mp4/util/atom/moov/udta/meta/ilst/GnreAtom.java
mp4/util/atom/moov/udta/meta/ilst/KeywAtom.java
mp4/util/atom/moov/udta/meta/ilst/PcstAtom.java
mp4/util/atom/moov/udta/meta/ilst/PurdAtom.java
mp4/util/atom/moov/udta/meta/ilst/PurlAtom.java
mp4/util/atom/moov/udta/meta/ilst/RtngAtom.java
mp4/util/atom/moov/udta/meta/ilst/StikAtom.java
mp4/util/atom/moov/udta/meta/ilst/TrknAtom.java
mp4/util/atom/moov/udta/meta/ilst/TvenAtom.java
mp4/util/atom/moov/udta/meta/ilst/TvesAtom.java
mp4/util/atom/moov/udta/meta/ilst/TvnnAtom.java
mp4/util/atom/moov/udta/meta/ilst/TvshAtom.java
mp4/util/atom/moov/udta/meta/ilst/TvsnAtom.java
mp4/util/atom/moov/udta/meta/IlstAtom.java
mp4/util/atom/moov/udta/MetaAtom.java
mp4/util/atom/MoovAtom.java
mp4/util/atom/MvhdAtom.java
mp4/util/atom/SmhdAtom.java
mp4/util/atom/StblAtom.java
mp4/util/atom/StcoAtom.java
mp4/util/atom/StscAtom.java
mp4/util/atom/StsdAtom.java
mp4/util/atom/StssAtom.java
mp4/util/atom/StszAtom.java
mp4/util/atom/SttsAtom.java
mp4/util/atom/TimeToSampleAtom.java
mp4/util/atom/TkhdAtom.java
mp4/util/atom/TrakAtom.java
mp4/util/atom/TrefAtom.java
mp4/util/atom/UdtaAtom.java
mp4/util/atom/UnknownAtom.java
mp4/util/atom/VmhdAtom.java
mp4/util/Mp4Dump.java
mp4/util/Mp4InterleaveWriter.java
mp4/util/MP4Log.java
mp4/util/Mp4Parser.java
mp4/util/Mp4Split.java

Original comment by kaspar.f...@gmail.com on 3 Oct 2009 at 9:02

GoogleCodeExporter commented 9 years ago
After looking & thinking a bit it may make sense to just rely on mp4.util.* (+ a
couple of extra classes) instead of starting from JavaMP4Splitter.java. 
JavaMP4Splitter may change as streambaby evolves (I consider it more part of the
streambaby framework than the MP4 framework).

I just pushed up a new class to SVN Mp4Test.java that shows how to use 
mp4.util.* to
copy a split Mp4 file.  (The main class takes "src.mp4 dst.mp4 
splitPosInSeconds").

The mp4.util classes have no logging dependencies (they already use an injection
method to set the logger).  So the only dependencies you have are:

mp4.util.*
com.unwiredappeal.tivo.utils.RandomAccessInputStream
com.unwiredappeal.tivo.utils.RandomAccessFileInputStream

About the threading in the original example, the threading is required.
PipedInputStream and PipedOutputStream are required to run in different threads 
(and
you get errors like you describe if they aren't...)

Even if you use just the mp4.util classes I think you will find you need to do
something similar--  mp4.util was originally written to output it's contents to 
a
stream (which is what you will see Mp4Test doing).  However to "serve" up a MP4 
file
it should act more as an InputStream.  I accomplished this in streambaby using 
the
PipedInputStream and PipedOutputStream classes running in seperate threads.

As far as how to deal with SVN and seperate projects using the code, I'm not 
really
sure how to deal with it for the moment.  I think it makes sense to wait and 
see how
things go and then deal with it.

Original comment by kearygri...@gmail.com on 4 Oct 2009 at 5:37