/*
* myLib - https://github.com/taktod/myLib
* Copyright (c) 2014 ttProject. All rights reserved.
*
* Licensed under The MIT license.
*/
package com.ttProject.container.test;
import org.apache.log4j.Logger;
import com.ttProject.container.IContainer;
import com.ttProject.container.IReader;
import com.ttProject.container.adts.AdtsUnit;
import com.ttProject.container.adts.AdtsUnitReader;
import com.ttProject.container.mpegts.MpegtsCodecType;
import com.ttProject.container.mpegts.MpegtsPacketReader;
import com.ttProject.container.mpegts.MpegtsPacketWriter;
import com.ttProject.container.mpegts.field.PmtElementaryField;
import com.ttProject.container.mpegts.field.PmtElementaryFieldFactory;
import com.ttProject.container.mpegts.type.Pat;
import com.ttProject.container.mpegts.type.Pes;
import com.ttProject.container.mpegts.type.Pmt;
import com.ttProject.container.mpegts.type.Sdt;
import com.ttProject.frame.Frame;
import com.ttProject.frame.IFrame;
import com.ttProject.frame.IVideoFrame;
import com.ttProject.frame.extra.VideoMultiFrame;
import com.ttProject.nio.channels.FileReadChannel;
import com.ttProject.nio.channels.IFileReadChannel;
/**
* make mpegts from 2 files.
* @author taktod
*/
public class FixMpegtsToTest {
/** logger */
private Logger logger = Logger.getLogger(FixMpegtsToTest.class);
// @Test
public void test() throws Exception {
logger.info("mixed out.h264.ts and out.aac");
IFileReadChannel h264Source = FileReadChannel.openFileReadChannel("out.h264.ts");
IFileReadChannel aacSource = FileReadChannel.openFileReadChannel("out.aac");
MpegtsPacketWriter writer = null;
try {
PmtElementaryFieldFactory factory = new PmtElementaryFieldFactory();
IReader mpegtsReader = new MpegtsPacketReader();
IReader adtsReader = new AdtsUnitReader();
writer = new MpegtsPacketWriter("fixed.ts");
// make sdt
Sdt sdt = new Sdt();
sdt.writeDefaultProvider("taktodTools", "mpegtsMuxer");
writer.addContainer(sdt);
// make pat
Pat pat = new Pat();
writer.addContainer(pat);
// make pmt
Pmt pmt = new Pmt(pat.getPmtPid());
PmtElementaryField h264Field = factory.makeNewField(MpegtsCodecType.VIDEO_H264);
pmt.setPcrPid(h264Field.getPid());
pmt.addNewField(h264Field);
PmtElementaryField aacField = factory.makeNewField(MpegtsCodecType.AUDIO_AAC);
pmt.addNewField(aacField);
writer.addContainer(pmt);
IContainer container = null;
IFrame frame = null;
long h264TimeDiff = 0; // mpegts data will not start with pts = 0, deal with diff
while((container = mpegtsReader.read(h264Source)) != null) {
if(container instanceof Pes) {
Pes pes = (Pes)container;
frame = pes.getFrame();
if(frame == null) {
continue;
}
logger.info(frame);
if(h264TimeDiff == 0) {
h264TimeDiff = frame.getPts();
}
// resetup pts, to make frame from pts = 0
if(frame instanceof VideoMultiFrame) {
((VideoMultiFrame) frame).setPts(frame.getPts() - h264TimeDiff);
for(IVideoFrame vFrame : ((VideoMultiFrame) frame).getFrameList()) {
if(vFrame.getPts() - h264TimeDiff < 0) {
((Frame)vFrame).setPts(0);
}
else {
((Frame)vFrame).setPts(vFrame.getPts() - h264TimeDiff);
}
}
}
else {
((Frame)frame).setPts(frame.getPts() - h264TimeDiff);
}
writer.addFrame(h264Field.getPid(), frame);
while((container = adtsReader.read(aacSource)) != null) {
if(container instanceof AdtsUnit) {
AdtsUnit adts = (AdtsUnit) container;
// pick up aac frame
IFrame aacFrame = adts.getFrame();
if(aacFrame == null) {
continue;
}
logger.info(aacFrame);
writer.addFrame(aacField.getPid(), aacFrame);
if(1.0f * aacFrame.getPts() / aacFrame.getTimebase() > 1.0f * (frame.getPts() - h264TimeDiff) / frame.getTimebase()) {
break;
}
}
}
}
}
}
catch(Exception e) {
logger.error("exception occured", e);
}
finally {
// close mpegtsWriter
if(writer != null) {
try {
writer.prepareTailer();
}
catch(Exception e) {
}
writer = null;
}
// close sources
if(h264Source != null) {
try {
h264Source.close();
}
catch(Exception e) {
}
h264Source = null;
}
if(aacSource != null) {
try {
aacSource.close();
}
catch(Exception e) {
}
aacSource = null;
}
}
}
}