简体   繁体   中英

Java .mp4 stream corruption at the end of a video - network error

Please help, My problem is to stream bytes from .mp4 with code on this page http://balusc.blogspot.ru/2009/02/fileservlet-supporting-resume-and.html and it is almost done properly, but the stream is always corrupted at the end of a movie ex.:

video is 57mins long - on 52 second fail occurred with message: "A network error cause the stream fail part way.", I've tried to test it several times, thought that it was really network problem - but it always the same. I presume there could be some specific issue with code with .mp4 to represent bytes for browser.

Any help would be appreciated.

The error msg in Browser: A network error caused the video download to fail part-way.

The problem should be in this part of code, now I suppose that the system Linux Ubuntu, may be JVM is not enough space with file size over 1.6Gb as C. Trimble mentioned in comments - probably I should allocate more memory on read stream socket for files or in JVM itself I don't know how (-Xms, -Xmx):

  private static void copy(RandomAccessFile input, OutputStream output, long start, long length) {
    byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
    int read;

    try {
      if (input.length() == length) {
        // Write full range.
        Logger.log("length==length read/write "+length);
        while ((read = input.read(buffer)) > 0) {
          output.write(buffer, 0, read);
        }
      } else {
        // Write partial range.
        input.seek(start);
        Logger.log("start length: "+start);
        long toRead = length+start;

        while ((read = input.read(buffer)) > 0) {
          if ((toRead -= read) > 0) {
            output.write(buffer, 0, read);
            Logger.log("toRead -= read read/write "+toRead);
//            output.write(buffer, 0, DEFAULT_BUFFER_SIZE);

          } else { // the end of a movie - ERROR APPEARS HERE !!!
            Logger.log("the end read/write "+toRead);
            output.write(buffer, 0, (int) toRead + read);
//            output.write(buffer, 0, DEFAULT_BUFFER_SIZE);
            break;
          }
        }
      }
    } catch (IOException ex) {
      Logger.log(Arrays.toString(ex.getStackTrace()), "error.log");
      Logger.log(ex.getMessage(), "error.log");
    }
  }

Response Content-Range from logs started from 1-st to the end when it falls:

2014-12-27 17:55:625 Content-Range: bytes 1784938496-1787737811/1787737812 2014-12-27 17:55:645 Content-Range: bytes 262144-1787737811/1787737812 2014-12-27 17:55:795 Content-Range: bytes 1048576-1787737811/1787737812 2014-12-27 17:55:190 Content-Range: bytes 1572864-1787737811/1787737812 2014-12-27 17:55:676 Content-Range: bytes 2097152-1787737811/1787737812 2014-12-27 17:55:195 Content-Range: bytes 2621440-1787737811/1787737812 2014-12-27 17:55:721 Content-Range: bytes 3145728-1787737811/1787737812 2014-12-27 17:55:421 Content-Range: bytes 786432-1787737811/1787737812 2014-12-27 17:55:992 Content-Range: bytes 1409024-1787737811/1787737812 2014-12-27 17:55:453 Content-Range: bytes 1835008-1787737811/1787737812 2014-12-27 17:55:34 Content-Range: bytes 2359296-1787737811/1787737812 2014-12-27 17:55:757 Content-Range: bytes 2883584-1787737811/1787737812 2014-12-27 17:55:340 Content-Range: bytes 5767168-1787737811/1787737812

All headers from FireBug Net tool - response:

Accept-Ranges   bytes
Content-Disposition inline;filename="True.Detective.S01E02.BDRip.720p.mp4"
Content-Length  1769137613
Content-Range   bytes 1572864-1770710476/1770710477
Content-Type    video/mp4
Date    Sat, 27 Dec 2014 17:53:54 GMT
Etag    True.Detective.S01E02.BDRip.720p.mp4_1770710477_1419450095000
Expires Sat, 03 Jan 2015 17:53:54 GMT
Last-Modified   Wed, 24 Dec 2014 19:41:35 GMT
Server  Apache-Coyote/1.1

Request headers:

Accept  video/webm,video/ogg,video/*;q=0.9,application/ogg;q=0.7,audio/*;q=0.6,*/*;q=0.5
Accept-Language ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Connection  keep-alive
Cookie  _ga=GA1.2.1399057170.1418569894; ci_session=a%3A5%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%22013f5e68900cbd78accb95573968b6f3%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A12%3A%22109.173.78.7%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A72%3A%22Mozilla%2F5.0+%28Windows+NT+6.3%3B+WOW64%3B+rv%3A34.0%29+Gecko%2F20100101+Firefox%2F34.0%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1419680981%3Bs%3A9%3A%22user_data%22%3Bs%3A0%3A%22%22%3B%7D4785741ee92c92e18475135f708e4283; PHPSESSID=s0cbpcnbqegb5u3312joe36510; _gat=1; _ym_visorc_27490695=w
Host    test.fast-seasons.ru:8080
Range   bytes=1572864-
Referer http://test.fast-seasons.ru:8080/tv/streaming?token=549ef20cd8a82
User-Agent  Mozilla/5.0 (Windows NT 6.3; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0

output in logs before fail - seems to be good before system/JVM fail because of bigger file or memory allocation:

2014-12-27 23:44:783 toRead -= read read/write 5792296
2014-12-27 23:44:783 toRead -= read read/write 5783080
2014-12-27 23:44:783 toRead -= read read/write 5773864
2014-12-27 23:44:783 toRead -= read read/write 5767168

Sometimes, in custom logs, I see the following exception:

2014-12-28 13:47:522 [org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:413), org.apache.tomcat.util.buf.ByteChunk.append(ByteChunk
.java:342), org.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:438), org.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:
426), org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:91), ru.fastseasons.streaming.StreamServlet.copy(StreamServlet.java:446)
, ru.fastseasons.streaming.StreamServlet.processRequest(StreamServlet.java:329), ru.fastseasons.streaming.StreamServlet.doGet(StreamServlet.java:100), javax.
servlet.http.HttpServlet.service(HttpServlet.java:620), javax.servlet.http.HttpServlet.service(HttpServlet.java:727), org.apache.catalina.core.ApplicationFil
terChain.internalDoFilter(ApplicationFilterChain.java:303), org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208), org.ap
ache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220), org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java
:122), org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170), org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.jav
a:98), org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950), org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.jav
a:116), org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408), org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11P
rocessor.java:1040), org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607), org.apache.tomcat.util.net.JIoEndpoint$
SocketProcessor.run(JIoEndpoint.java:313), java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145), java.util.concurrent.ThreadPoolEx
ecutor$Worker.run(ThreadPoolExecutor.java:615), java.lang.Thread.run(Thread.java:745)]
2014-12-28 13:47:522 null

Sure I looked at line 446 and saw the read variable passed as 3d argument to read number of bytes containing in it, but there shouldn't be program problems with this, because read var is always >0 through while loop condition.

The strange behaviour as I suppose is that it happens with files of .mp4 format larger 1Gb, may be this is Linux or JVM memory suffocation - I don't know and I don't know how to test it. Also I've tried to look at ulimit -r -l

real-time priority              (-r) 95
max locked memory       (kbytes, -l) unlimited

There are actually 3 rows in logs for every mp4/video stream (when the video plays through browser Chrome on Windows) - seems to be quite normal, here it is:

2014-12-28 22:29:167 Content-Range: bytes 0-1180454117/1180454118
2014-12-28 22:29:168 Content-Length: 1180454118
2014-12-28 22:29:601 Content-Range: bytes 1178816938-1180454117/1180454118
2014-12-28 22:29:601 Content-Length: 1637180
2014-12-28 22:29:768 Content-Range: bytes 1178816986-1180454117/1180454118
2014-12-28 22:29:769 Content-Length: 1180454070

Works in Chrome, thx to EJP, but still problems in FF.

Edits implemented in code after @EJP correction:

long toRead = length;

while (toRead > 0 && (read = input.read(buffer, 0, (int)Math.min(buffer.length, toRead))) > 0)
{
    output.write(buffer, 0, read);
    toRead -= read;
}
long toRead = length+start;

The problem is here. It should be:

long toRead = length;

However your code can be simplified considerably:

while (toRead > 0 && (read = input.read(buffer, 0, (int)Math.min(buffer.length, toRead))) > 0)
{
    output.write(buffer, 0, read);
    toRead -= read;
}

E&OE

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM