Debugging more video streaming. Works without regenerating onMetadata.
This commit is contained in:
parent
494c0e5930
commit
a58b074873
4 changed files with 60 additions and 22 deletions
|
|
@ -46,6 +46,7 @@ public class FlvFilter extends OutputStream {
|
|||
|
||||
private FlvMetadata metadata;
|
||||
private FlvMetadata extraMetadata;
|
||||
private int bodyLen = 0;
|
||||
|
||||
public FlvFilter(FlvReceiver receiver, FlvMetadata metadata) {
|
||||
this.receiver = receiver;
|
||||
|
|
@ -151,7 +152,7 @@ public class FlvFilter extends OutputStream {
|
|||
headerWritten = true;
|
||||
} else {
|
||||
log.warn("SCRIPTDATA out of order");
|
||||
receiver.writeBody(currentBox);
|
||||
writeBody();
|
||||
}
|
||||
} else if (currentTagType == FLV_TAG_VIDEO || currentTagType == FLV_TAG_AUDIO) {
|
||||
if (!headerWritten) {
|
||||
|
|
@ -166,14 +167,21 @@ public class FlvFilter extends OutputStream {
|
|||
} else { // currentTagType == FLV_TAG_AUDIO
|
||||
metadata.addAudioFrame(currentTagPos, currentTagTimestamp);
|
||||
}
|
||||
receiver.writeBody(currentBox);
|
||||
metadata.setFileSize(currentTagPos + currentTagSize);
|
||||
writeBody();
|
||||
} else {
|
||||
log.error("Unknown box type: " + currentTagType);
|
||||
receiver.writeBody(currentBox);
|
||||
writeBody();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private void writeBody() {
|
||||
receiver.writeBody(currentBox);
|
||||
bodyLen += currentBox.length;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
|
|
@ -184,9 +192,11 @@ public class FlvFilter extends OutputStream {
|
|||
|
||||
public void generateHeader() throws IOException {
|
||||
|
||||
metadata.setFileSize(fileHeader.length + incomingMetadataLength + bodyLen);
|
||||
int metadataLength = metadata.calculateLength();
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(fileHeader.length + metadataLength);
|
||||
out.write(fileHeader);
|
||||
metadata.setFileSize(fileHeader.length + metadataLength + bodyLen);
|
||||
metadata.setFileOffsetDelta(metadataLength - incomingMetadataLength);
|
||||
metadata.writeOnMetadata(out);
|
||||
|
||||
|
|
|
|||
|
|
@ -149,17 +149,17 @@ public class MovieCoder {
|
|||
|
||||
class EncodingProcess implements Runnable, FlvFilter.FlvReceiver {
|
||||
|
||||
final int chunkSize = 4 * 65536;
|
||||
File file;
|
||||
Thumbnail thumbnail;
|
||||
Dimension targetSize;
|
||||
ArrayList<EncodingProcessListener> listeners = new ArrayList<EncodingProcessListener>();
|
||||
Chunk currentChunk = null;
|
||||
int chunkPos;
|
||||
int remainingCapacity;
|
||||
int chunkNo = 0;
|
||||
FlvFilter filter;
|
||||
String dbKey;
|
||||
private final int chunkSize = 4 * 65536;
|
||||
private File file;
|
||||
private Thumbnail thumbnail;
|
||||
private Dimension targetSize;
|
||||
private ArrayList<EncodingProcessListener> listeners = new ArrayList<EncodingProcessListener>();
|
||||
private Chunk currentChunk = null;
|
||||
private int chunkPos;
|
||||
private int remainingCapacity;
|
||||
private int chunkNo = 0;
|
||||
private FlvFilter filter;
|
||||
private String dbKey;
|
||||
|
||||
public EncodingProcess(File file, Thumbnail thumbnail, Dimension size) {
|
||||
this.file = file;
|
||||
|
|
@ -219,7 +219,7 @@ public class MovieCoder {
|
|||
p.getOutputStream().close();
|
||||
InputStream movieStream = p.getInputStream();
|
||||
InputStream diagnostic = p.getErrorStream();
|
||||
new Thread(new ErrorStreamPumper(diagnostic)).start();
|
||||
new Thread(new ErrorStreamPumper("ffmpeg", diagnostic)).start();
|
||||
|
||||
byte[] buffer = new byte[65536];
|
||||
int len;
|
||||
|
|
@ -228,6 +228,9 @@ public class MovieCoder {
|
|||
}
|
||||
filter.flush();
|
||||
endLastChunk();
|
||||
// Generate header again to get updated metadata
|
||||
// TODO (knut 09 JUL 2011) Figure out why the generated header doesn't work
|
||||
// filter.generateHeader();
|
||||
} catch (Exception e) {
|
||||
log.error("uh?", e);
|
||||
movieDb.delete(dbKey);
|
||||
|
|
@ -282,6 +285,7 @@ public class MovieCoder {
|
|||
System.arraycopy(data, inputPos, currentChunk.bits, chunkPos, copyLen);
|
||||
chunkPos += copyLen;
|
||||
remainingCapacity -= copyLen;
|
||||
inputPos += copyLen;
|
||||
remainingInput -= copyLen;
|
||||
if (remainingCapacity == 0) {
|
||||
endChunk();
|
||||
|
|
@ -299,6 +303,7 @@ public class MovieCoder {
|
|||
|
||||
private void endChunk() {
|
||||
|
||||
log.info("Receiving chunk " + chunkNo);
|
||||
movieDb.store(dbKey, chunkNo, currentChunk);
|
||||
currentChunk = null;
|
||||
notifyListeners(chunkNo, false);
|
||||
|
|
@ -328,18 +333,22 @@ public class MovieCoder {
|
|||
|
||||
class ErrorStreamPumper implements Runnable {
|
||||
|
||||
InputStream is;
|
||||
public ErrorStreamPumper(InputStream is) {
|
||||
private InputStream is;
|
||||
private String name;
|
||||
|
||||
public ErrorStreamPumper(String processName, InputStream is) {
|
||||
this.name = processName;
|
||||
this.is = is;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
org.slf4j.Logger diag = org.slf4j.LoggerFactory.getLogger(this.name);
|
||||
try {
|
||||
LineNumberReader lnr = new LineNumberReader(new InputStreamReader(is));
|
||||
String line;
|
||||
while ((line = lnr.readLine()) != null) {
|
||||
log.info(line);
|
||||
diag.info(line);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("stderr?", e);
|
||||
|
|
@ -352,7 +361,11 @@ public class MovieCoder {
|
|||
// range requests etcetera
|
||||
public void stream(File file, Thumbnail thumbnail, String size, OutputStream out) throws IOException, InterruptedException {
|
||||
|
||||
grabStream(file, thumbnail, size).stream(out);
|
||||
try {
|
||||
grabStream(file, thumbnail, size).stream(out);
|
||||
} catch (Exception e) {
|
||||
log.error("stream fail", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String key(File file, Dimension size) {
|
||||
|
|
@ -412,9 +425,17 @@ public class MovieCoder {
|
|||
public void stream(OutputStream out) throws IOException, InterruptedException {
|
||||
|
||||
while (!done()) {
|
||||
while (chunk != null) {
|
||||
|
||||
if (chunk == null) {
|
||||
log.info("Looking for " + chunkNo);
|
||||
chunk = movieDb.load(key, chunkNo);
|
||||
}
|
||||
if (chunk != null) {
|
||||
log.info("Sending " + chunkNo + ", " + chunk.bits.length + " bytes");
|
||||
out.write(chunk.bits);
|
||||
chunk = movieDb.load(key, ++chunkNo);
|
||||
chunk = null;
|
||||
chunkNo++;
|
||||
continue;
|
||||
}
|
||||
if (!done()) {
|
||||
if (ep != null) {
|
||||
|
|
@ -430,6 +451,7 @@ public class MovieCoder {
|
|||
if (ep != null) {
|
||||
ep.removeListener(this);
|
||||
}
|
||||
log.info("done sending");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -344,8 +344,11 @@ public class AlbumServlet
|
|||
try {
|
||||
String size = req.getParameter("size");
|
||||
res.setStatus(HttpServletResponse.SC_OK);
|
||||
/*
|
||||
res.setDateHeader("Last-Modified", entry.getPath().lastModified());
|
||||
res.setDateHeader("Expires", System.currentTimeMillis() + (30 * 24 * 3600 * 1000L)); // 30 days
|
||||
*/
|
||||
res.setHeader("Cache-control", "no-cache");
|
||||
res.setContentType("video/x-flv");
|
||||
movieCoder.stream(entry.getPath(), entry.getThumbnail(), size, res.getOutputStream());
|
||||
} catch (Exception ex) {
|
||||
|
|
|
|||
|
|
@ -37,4 +37,7 @@ public class FlvFilterTest extends TestCase {
|
|||
assertEquals("HEADER[252]BODY[0]HEADER[579]BODY[911684]", buf.toString());
|
||||
}
|
||||
|
||||
public void testFoo() {
|
||||
System.out.println(0x40128);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue