use of com.feeyo.hls.ts.segmenter.H264TsSegmenter.AvcResult in project feeyo-hlsserver by variflight.
the class AacH264MixedTsSegmenter method writeFrame.
private void writeFrame() {
if (isTailAvc)
return;
while (!avcResultDeque.isEmpty()) {
AvcResult result = avcResultDeque.pop();
for (FrameData avcFrame : result.avcFrames) avcFrameCache.offer(avcFrame);
if (result.isTailAvc) {
isTailAvc = true;
break;
}
}
while (!aacFrameCache.isEmpty() && !avcFrameCache.isEmpty()) {
FrameData avcFrame = avcFrameCache.peek();
if (aacFrameCache.peek().pts < avcFrame.pts) {
FrameData frameData = aacFrameCache.pop();
byte[] aacTsSegment = tsWriter.write(isFirstAacPes, FrameDataType.MIXED, frameData);
if (aacTsSegment != null) {
tsSegmentLen += aacTsSegment.length;
tsSecs[tsSecsPtr++] = aacTsSegment;
}
isFirstAacPes = false;
maxAacPts = maxAacPts > frameData.pts ? maxAacPts : frameData.pts;
mixPts = mixPts > maxAacPts ? mixPts : maxAacPts;
} else {
FrameData frameData = avcFrameCache.pop();
byte[] avcTsSegment = tsWriter.write(isFirstAvcPes, FrameDataType.MIXED, frameData);
if (avcTsSegment != null) {
tsSegmentLen += avcTsSegment.length;
tsSecs[tsSecsPtr++] = avcTsSegment;
}
isFirstAvcPes = false;
maxAvcPts = maxAvcPts > frameData.pts ? maxAvcPts : frameData.pts;
mixPts = mixPts > maxAvcPts ? mixPts : maxAvcPts;
}
}
waitAac = (aacFrameCache.isEmpty() && maxAacPts + aacTsSegmenter.getPtsIncPerFrame() < maxAvcPts + h264TsSegmenter.getPtsIncPerFrame());
}
use of com.feeyo.hls.ts.segmenter.H264TsSegmenter.AvcResult in project feeyo-hlsserver by variflight.
the class AacH264MixedTsSegmenter method segment.
/**
* @param V5PacketType.AAC_STREAM -> rawData is a full-frame accData
* V5PacketType.H264_STREAM -> rawData is h264 byte dataStream
*/
@Override
protected byte[] segment(byte rawDataType, byte[] rawData, byte[] reserved) {
if (reserved.length != 8) {
LOGGER.error("## Reserved area doesn't contain index!");
return null;
}
if (ctime == 0) {
headFrameType = rawDataType;
ctime = System.currentTimeMillis();
}
// from 0
long index = ByteUtil.bytesToLong(reserved[0], reserved[1], reserved[2], reserved[3], reserved[4], reserved[5], reserved[6], reserved[7]);
switch(rawDataType) {
case V5PacketType.AAC_STREAM:
if (headFrameType != V5PacketType.AAC_STREAM && !syncPtsBase) {
aacTsSegmenter.setPts((System.currentTimeMillis() - ctime) * 90);
syncPtsBase = true;
}
if (index == preAacIndex + 1) {
preAacIndex++;
skipAac = false;
FrameData aacFrame = aacTsSegmenter.process(rawData);
if (aacFrame != null)
aacFrameCache.offer(aacFrame);
preAacCTime = System.currentTimeMillis();
} else if (index > preAacIndex + 1) {
try {
while (!aacLocking.compareAndSet(false, true)) {
}
aacRawCache.add(new RawItem(rawData, index));
Collections.sort(aacRawCache, new RawDescComparator());
skipAac = true;
} finally {
aacLocking.set(false);
}
}
while (!aacRawCache.isEmpty() && aacRawCache.get(0).index == preAacIndex + 1) {
preAacIndex++;
skipAac = false;
FrameData aacFrame = aacTsSegmenter.process(aacRawCache.remove(0).rawData);
if (aacFrame != null)
aacFrameCache.offer(aacFrame);
preAacCTime = System.currentTimeMillis();
}
if (waitAac)
writeFrame();
break;
case V5PacketType.H264_STREAM:
try {
while (!avcLocking.compareAndSet(false, true)) {
}
if (headFrameType != V5PacketType.H264_STREAM && !syncPtsBase) {
h264TsSegmenter.setPts((System.currentTimeMillis() - ctime) * 90);
syncPtsBase = true;
}
if (index == preAvcIndex + 1) {
skipAvc = false;
preAvcIndex = index;
AvcResult avcResult = h264TsSegmenter.process(rawData);
if (avcResult != null)
avcResultDeque.offer(avcResult);
preAvcCTime = System.currentTimeMillis();
} else if (index > preAvcIndex + 1) {
avcRawCache.add(new RawItem(rawData, index));
Collections.sort(avcRawCache, new RawDescComparator());
skipAvc = true;
}
while (!avcRawCache.isEmpty() && avcRawCache.get(0).index == preAvcIndex + 1) {
preAvcIndex++;
skipAvc = false;
AvcResult avcResult = h264TsSegmenter.process(avcRawCache.remove(0).rawData);
if (avcResult != null)
avcResultDeque.offer(avcResult);
preAvcCTime = System.currentTimeMillis();
}
if (isTailAvc && !waitAac) {
if (tsSecs[0] == null)
return null;
tsSegTime = (mixPts - ptsBase) / 90000F;
isTailAvc = false;
// Consider video in 10 seconds.
if (!isLowTenSec && tsSecs[0] != null && tsSegTime < 10F && System.currentTimeMillis() - ctime > 60 * 1000) {
isLowTenSec = true;
return write2Ts();
}
return tsSecs[0] == null || tsSegTime < 10F ? null : write2Ts();
}
while (!avcResultDeque.isEmpty()) {
writeFrame();
if (isTailAvc && !waitAac) {
while (!avcFrameCache.isEmpty()) {
if (avcFrameCache.isEmpty())
break;
while (!waitAac) {
if (avcFrameCache.isEmpty())
break;
FrameData frameData = avcFrameCache.pop();
byte[] aacTsSegment = tsWriter.write(isFirstAvcPes, FrameDataType.MIXED, frameData);
if (aacTsSegment != null) {
tsSegmentLen += aacTsSegment.length;
tsSecs[tsSecsPtr++] = aacTsSegment;
}
isFirstAvcPes = false;
mixPts = mixPts > frameData.pts ? mixPts : frameData.pts;
waitAac = (aacFrameCache.isEmpty() && maxAacPts + aacTsSegmenter.getPtsIncPerFrame() < maxAvcPts + h264TsSegmenter.getPtsIncPerFrame());
}
}
tsSegTime = (mixPts - ptsBase) / 90000F;
isTailAvc = false;
// Consider video in 10 seconds.
if (!isLowTenSec && tsSecs[0] != null && tsSegTime < 10F && System.currentTimeMillis() - ctime > 60 * 1000) {
isLowTenSec = true;
return write2Ts();
}
return tsSegTime < 10F ? null : write2Ts();
}
}
} finally {
avcLocking.set(false);
}
break;
}
return null;
}