Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Packet192 #73

Merged
merged 23 commits into from
Aug 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f658160
inlined parseStream(), renamed parsePSITables to parseStream
EricBerendsen Jun 30, 2024
672ba2e
removed commented code
EricBerendsen Jun 30, 2024
05ed257
Fixed FEC/timestamp not shown in Tree when no payload, refactoring
EricBerendsen Jun 30, 2024
58f6ba0
first attempt at TP_extra_header support for 192 byte packets
EricBerendsen Jun 30, 2024
a5dda80
added rollOverHelper to reconstruct a 'PCR'
EricBerendsen Jul 1, 2024
4301b64
TimeStampChart handles AVCHD stream correct, PCR is a straight line
EricBerendsen Jul 3, 2024
bec6fbc
reverse loops, remove needless iteration over PIDs
EricBerendsen Jul 4, 2024
29abff8
refactor determining interval boundaries
EricBerendsen Jul 4, 2024
48d8e3c
add packetATS as helper for arrival time AVCHD Packets
EricBerendsen Jul 5, 2024
d24b279
BitRateChart can now handle AVCHD streams
EricBerendsen Jul 5, 2024
efc3c9b
packet No is always int
EricBerendsen Jul 5, 2024
96a42fd
AVCHD support for repetition rate in TableSection
EricBerendsen Jul 5, 2024
0a41a09
add fix for Humax ATS quirk, make configurable in GUI
EricBerendsen Jul 6, 2024
deecc7f
remove roll_over from AVCHDPacket, keep that in TransportStream
EricBerendsen Jul 6, 2024
e97cbf8
refactored BarChart in prepartion for AVCHD support
EricBerendsen Jul 7, 2024
cc08892
BarChart now supports AVCHD streams
EricBerendsen Jul 7, 2024
72ce915
make right panel single selection, added 1000 to STEP_OPTIONS
EricBerendsen Aug 4, 2024
1db76f6
added comments
EricBerendsen Aug 4, 2024
999dd33
create RollOverHelper only for AVCHD streams
EricBerendsen Aug 4, 2024
2b6d19f
cleanup unused parameters
EricBerendsen Aug 4, 2024
bccb4f4
cleanup
EricBerendsen Aug 4, 2024
6a0f14f
improve msg
EricBerendsen Aug 4, 2024
26e622d
add description AVCHD to packet size option
EricBerendsen Aug 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 141 additions & 0 deletions src/main/java/nl/digitalekabeltelevisie/data/mpeg/AVCHDPacket.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/**
*
* http://www.digitalekabeltelevisie.nl/dvb_inspector
*
* This code is Copyright 2009-2024 by Eric Berendsen (e_berendsen@digitalekabeltelevisie.nl)
*
* This file is part of DVB Inspector.
*
* DVB Inspector is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DVB Inspector is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DVB Inspector. If not, see <http://www.gnu.org/licenses/>.
*
* The author requests that he be notified of any application, applet, or
* other binary that makes use of this code, but that's more out of curiosity
* than anything and is not required.
*
*/

package nl.digitalekabeltelevisie.data.mpeg;

import static nl.digitalekabeltelevisie.util.Utils.*;

import java.awt.Color;
import java.util.Arrays;

import javax.swing.tree.DefaultMutableTreeNode;

import nl.digitalekabeltelevisie.controller.KVP;
import nl.digitalekabeltelevisie.util.RangeHashMap;
import nl.digitalekabeltelevisie.util.Utils;

/**
* AVCHD and Blu-ray use same format for 192 byte TS packets, first 4 bytes are tp_extra_header.
* See Table 3-34 TP_extra_header. in "Advanced Access Content System (AACS) Blu-ray Disc Pre-recorded Book" (AACS_Spec_BD_Prerecorded_Final_0.951.pdf)
*
* See <a href="https://stackoverflow.com/questions/32354754/how-to-use-timestamps-for-seeking-in-m2ts-files">https://stackoverflow.com/questions/32354754/how-to-use-timestamps-for-seeking-in-m2ts-files</a>
*
*/
public class AVCHDPacket extends TSPacket {

byte[] tp_extra_header;

int arrivalTimestamp;

public AVCHDPacket(byte[] buf, int no, TransportStream ts) {
super(Arrays.copyOfRange(buf,4,192), no, ts);
tp_extra_header = Arrays.copyOf(buf,4);
arrivalTimestamp = getInt(tp_extra_header,0,4,MASK_30BITS);
}


public byte[] getTP_extra_header() {
return tp_extra_header;
}

public int getCopyPermissionIndicator() {
return (tp_extra_header[0] & 0b1100_0000)>>6;
}

public int getArrivalTimestamp() {
return arrivalTimestamp;
}


@Override
public DefaultMutableTreeNode getJTreeNode(final int modus) {

final DefaultMutableTreeNode t = new DefaultMutableTreeNode(new KVP(buildNodeLabel(),this));
final DefaultMutableTreeNode tpHeaderNode = new DefaultMutableTreeNode(new KVP("tp_extra_header",tp_extra_header,null));
tpHeaderNode.add(new DefaultMutableTreeNode(new KVP("Copy_permission_indicator",getCopyPermissionIndicator(),null)));
tpHeaderNode.add(new DefaultMutableTreeNode(new KVP("Arrival_time_stamp",arrivalTimestamp,printPCRTime(arrivalTimestamp))));
t.add(tpHeaderNode);
addMainPacketDetails(modus, t);
return t;
}

@Override
public String getHTML() {
final StringBuilder s = new StringBuilder();

s.append("Packet: ").append(packetNo);
if(packetOffset!=-1){
s.append("<br>File Offset: ").append(packetOffset);
}
if(transportStream!=null){
s.append("<br>Time: ").append(transportStream.getPacketTime(packetNo));
final short pid = transportStream.getPacket_pid(packetNo);
s.append("<br>").append(escapeHtmlBreakLines(transportStream.getShortLabel(pid))).append("<br>");
}



final RangeHashMap<Integer, Color> coloring = new RangeHashMap<>();

//tp_extra_header
Utils.appendHeader(s, "TP_extra_header: 0x" + toHexString(tp_extra_header, 0, 4), FEC_COLOR);
coloring.put(0, 4, FEC_COLOR);


s.append("<br>Copy_permission_indicator: ").append(getCopyPermissionIndicator());
s.append("<br>Arrival_time_stamp: ").append(getArrivalTimestamp()).append(" (").append(printPCRTime(getArrivalTimestamp())).append(")");
s.append("</span><br>");

addBasicPacketDetails(s, 4, coloring);

byte[] buf = new byte[192];

System.arraycopy(tp_extra_header, 0, buf, 0, 4);
System.arraycopy(buffer, 0, buf, 4, 188);

s.append("<br><b>Data:</b><br>").append(getHTMLHexviewColored(buf,0,192,coloring));
return s.toString();
}



/**
* for AVCHD file time corresponds to TP_header ATS (plus roll over
*/

// TODO implement quirks mode for Humax, where last 9 bitss only use values 0-299 (like PCR)
@Override
public long getTimeBase() {
return transportStream.getAVCHDPacketTime(packetNo);
}


@Override
public String toString() {
return super.toString() + " , arrivalTimestamp: " + arrivalTimestamp;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
*
* http://www.digitalekabeltelevisie.nl/dvb_inspector
*
* This code is Copyright 2009-2012 by Eric Berendsen (e_berendsen@digitalekabeltelevisie.nl)
* This code is Copyright 2009-2024 by Eric Berendsen (e_berendsen@digitalekabeltelevisie.nl)
*
* This file is part of DVB Inspector.
*
Expand All @@ -28,7 +28,6 @@
package nl.digitalekabeltelevisie.data.mpeg;

public final class MPEGConstants {

/**
*
*/
Expand All @@ -37,6 +36,11 @@ private MPEGConstants() {
}
public final static byte sync_byte=0x47;
public final static int PAYLOAD_PACKET_LENGTH=188;

public final static int AVCHD_PACKET_LENGTH = 192;

public final static int system_clock_frequency=27000000;

public final static int NO_PCR_PID=0x1FFF;
public static final int MAX_PIDS = 8192;
}
14 changes: 7 additions & 7 deletions src/main/java/nl/digitalekabeltelevisie/data/mpeg/PID.java
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ private record ContinuityError(int lastPacketNo, int lastCCounter, int newPacket
private int dup_found=0; // number of times current packet is duplicated.
private PCR lastPCR;
private PCR firstPCR;
private long lastPCRpacketNo = -1;
private long firstPCRpacketNo =-1;
private int lastPCRpacketNo = -1;
private int firstPCRpacketNo =-1;
private long pcr_count =-1;
protected TransportStream parentTransportStream = null;

Expand Down Expand Up @@ -224,10 +224,10 @@ private void startPesPacket(final TSPacket packet, final PID parentPID) {

final int pts_dts_flags = pesHeader.getPts_dts_flags();
if ((pts_dts_flags == 2) || (pts_dts_flags == 3)) { // PTS present,
ptsList.add(new TimeStamp(packet.getPacketNo(), pesHeader.getPts()));
ptsList.add(new TimeStamp(packet.getTimeBase(), pesHeader.getPts()));
}
if (pts_dts_flags == 3) { // DTS present,
dtsList.add(new TimeStamp(packet.getPacketNo(), pesHeader.getDts()));
dtsList.add(new TimeStamp(packet.getTimeBase(), pesHeader.getDts()));
}
}
} catch (Exception e) {
Expand Down Expand Up @@ -387,7 +387,7 @@ private AdaptationField handleAdaptationField(final TSPacket packet) {
AdaptationField adaptationField;
try{
adaptationField = packet.getAdaptationField();
processAdaptationField(adaptationField,packet.getPacketNo());
processAdaptationField(adaptationField,packet.getPacketNo(),packet.getTimeBase());
}catch(final RuntimeException re){ // might be some error in adaptation field, it is not well protected
logger.log(Level.WARNING, "Error getting adaptationField", re);
adaptationField = null;
Expand Down Expand Up @@ -418,12 +418,12 @@ private void updateMegaFrameInitializationPacket(final TSPacket packet) {
}


private void processAdaptationField(AdaptationField adaptationField, int packetNo) {
private void processAdaptationField(AdaptationField adaptationField, int packetNo, long timeBase) {
processTEMI(adaptationField, temiList, packetNo);
if (adaptationField.isPCR_flag()) {
final PCR newPCR = adaptationField.getProgram_clock_reference();
if(PreferencesManager.isEnablePcrPtsView()) {
pcrList.add(new TimeStamp(packetNo, newPCR.getProgram_clock_reference_base()));
pcrList.add(new TimeStamp(timeBase, newPCR.getProgram_clock_reference_base()));
}
if ((firstPCR != null) && !adaptationField.isDiscontinuity_indicator()) {
final long packetsDiff = packetNo - firstPCRpacketNo;
Expand Down
110 changes: 59 additions & 51 deletions src/main/java/nl/digitalekabeltelevisie/data/mpeg/TSPacket.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,16 @@ public class TSPacket implements HTMLSource, TreeNode{

private static final Logger logger = Logger.getLogger(TSPacket.class.getName());
private static final String ERROR_PARSING_ADAPTATION_FIELD = "Error parsing AdaptationField";
final private byte[] buffer ;
protected final byte[] buffer ;

private int packetNo=-1;
final private static Color HEADER_COLOR = new Color(0x0000ff);
final private static Color ADAPTATION_FIELD_COLOR = new Color(0x008000);
final private static Color FEC_COLOR = new Color(0x800080);
final private static Color PES_HEADER_COLOR = new Color(0x800000);
private static final Color ERROR_COLOR = new Color(0xFF0000);
final private TransportStream transportStream;
private long packetOffset = -1;
protected int packetNo=-1;
final protected static Color HEADER_COLOR = new Color(0x0000ff);
final protected static Color ADAPTATION_FIELD_COLOR = new Color(0x008000);
final protected static Color FEC_COLOR = new Color(0x800080);
final protected static Color PES_HEADER_COLOR = new Color(0x800000);
final protected static Color ERROR_COLOR = new Color(0xFF0000);
final protected TransportStream transportStream;
protected long packetOffset = -1;

private PesHeader pesHeader = null;

Expand Down Expand Up @@ -110,17 +110,6 @@ public TSPacket(final byte[] buf, final int no, final TransportStream ts) {
buffer=Arrays.copyOf(buf, buf.length); //buf should be copied, or else PID.getLast_packet() will always point to last packet parsed, regardless of the actual pid.
packetNo = no;
transportStream = ts;

// if((getAdaptationFieldControl()==2)||(getAdaptationFieldControl()==3)) { //Adaptation field present
// getAdaptationField();
// }
//
// if(getPayloadUnitStartIndicator()==1){
// if((getAdaptationFieldControl()!=1)&&(getAdaptationFieldControl()!=3)){
// System.out.println("Error: TSPacket:"+packetNo+", PID:"+getPID()+", If a PID is carrying PES packets or PSI sections, and payload_unit_start_indicator is set to 1, then test that adaptation_field_control is ‘01’ or ‘11’”");
// }
// }
//
}

public int getTransportScramblingControl(){
Expand Down Expand Up @@ -248,6 +237,12 @@ public int getPacketNo() {
return packetNo;
}

/**
* for CBR file time corresponds to packetNo
*/
public long getTimeBase() {
return packetNo;
}
/**
* @param packet_no
*/
Expand All @@ -272,9 +267,25 @@ public String getHTML() {
s.append("<br>").append(escapeHtmlBreakLines(transportStream.getShortLabel(pid))).append("<br>");
}

Utils.appendHeader(s, "Header:", HEADER_COLOR);
final RangeHashMap<Integer, Color> coloring = new RangeHashMap<>();
coloring.put(0, 3, HEADER_COLOR);
addBasicPacketDetails(s, 0, coloring);

// FEC / timestamp
if(buffer.length>PAYLOAD_PACKET_LENGTH){
final RangeHashMap<Integer, Color> localColoring = new RangeHashMap<>();
//for some reason using getHTMLHexview resets color, so we use getHTMLHexviewColored with only one color.
localColoring.put(0, buffer.length-PAYLOAD_PACKET_LENGTH, FEC_COLOR);
Utils.appendHeader(s, "FEC/timestamp:", FEC_COLOR);
s.append(getHTMLHexviewColored(buffer,PAYLOAD_PACKET_LENGTH,buffer.length-PAYLOAD_PACKET_LENGTH,localColoring)).append("</span>");
coloring.put(PAYLOAD_PACKET_LENGTH, buffer.length, FEC_COLOR);
}
s.append("<br><b>Data:</b><br>").append(getHTMLHexviewColored(buffer,0,buffer.length,coloring));
return s.toString();
}

protected void addBasicPacketDetails(final StringBuilder s, int coloringOffset, final RangeHashMap<Integer, Color> coloring) {
Utils.appendHeader(s, "Header:", HEADER_COLOR);
coloring.put(coloringOffset, coloringOffset + 3, HEADER_COLOR);

s.append("<br>sync_byte: ").append(getHexAndDecimalFormattedString(getSyncByte()));
s.append("<br>transport_error_indicator: ").append(getTransportErrorIndicator());
Expand All @@ -297,7 +308,7 @@ public String getHTML() {
if(adaptationField!=null){
Utils.appendHeader(s, "adaptation_field:", ADAPTATION_FIELD_COLOR);
s.append(adaptationField.getHTML()).append("<br></span>");
coloring.put(4, 4+adaptationField.getAdaptation_field_length(), ADAPTATION_FIELD_COLOR);
coloring.put(coloringOffset + 4, coloringOffset + 4 + adaptationField.getAdaptation_field_length(), ADAPTATION_FIELD_COLOR);
}

// PES header
Expand All @@ -314,25 +325,13 @@ public String getHTML() {
s.append("<br>").append(Utils.getChildrenAsHTML(treeNode));
s.append("</span>");
if(pesHeaderView.hasExtendedHeader()){
coloring.put(payloadStart, payloadStart+8+pesHeaderView.getPes_header_data_length(), PES_HEADER_COLOR);
coloring.put(coloringOffset + payloadStart, coloringOffset + payloadStart+8+pesHeaderView.getPes_header_data_length(), PES_HEADER_COLOR);
}else{
coloring.put(payloadStart, payloadStart+5, PES_HEADER_COLOR);
coloring.put(coloringOffset + payloadStart, coloringOffset + payloadStart+5, PES_HEADER_COLOR);
}
}
}
}

// FEC / timestamp
if(buffer.length>PAYLOAD_PACKET_LENGTH){
final RangeHashMap<Integer, Color> localColoring = new RangeHashMap<>();
//for some reason using getHTMLHexview resets color, so we use getHTMLHexviewColored with only one color.
localColoring.put(0, buffer.length-PAYLOAD_PACKET_LENGTH, FEC_COLOR);
Utils.appendHeader(s, "FEC/timestamp:", FEC_COLOR);
s.append(getHTMLHexviewColored(buffer,PAYLOAD_PACKET_LENGTH,buffer.length-PAYLOAD_PACKET_LENGTH,localColoring)).append("</span>");
coloring.put(PAYLOAD_PACKET_LENGTH, buffer.length, FEC_COLOR);
}
s.append("<br><b>Data:</b><br>").append(getHTMLHexviewColored(buffer,0,buffer.length,coloring));
return s.toString();
}

/**
Expand All @@ -355,18 +354,15 @@ private int getSyncByte() {
@Override
public DefaultMutableTreeNode getJTreeNode(final int modus) {

final StringBuilder l = new StringBuilder("transport_packet [").append(packetNo).append("]");
if((getAdaptationFieldControl()==2)||(getAdaptationFieldControl()==3)) { //Adaptation field present
l.append(" (adaptation field)");
}
if(hasPayload()) { //payload present
l.append(" (payload)");
}
if(isPayloadUnitStartIndicator()){
l.append(" (payload start)");
final DefaultMutableTreeNode t = new DefaultMutableTreeNode(new KVP(buildNodeLabel(), this));
addMainPacketDetails(modus, t);
if(buffer.length>PAYLOAD_PACKET_LENGTH){
t.add(new DefaultMutableTreeNode(new KVP("FEC/timestamp",buffer,PAYLOAD_PACKET_LENGTH ,buffer.length - PAYLOAD_PACKET_LENGTH, null)));
}
return t;
}

final DefaultMutableTreeNode t = new DefaultMutableTreeNode(new KVP(l.toString(), this));
protected void addMainPacketDetails(final int modus, final DefaultMutableTreeNode t) {
t.add(new DefaultMutableTreeNode(new KVP("sync_byte",getSyncByte() ,"Should be 0x47")));
t.add(new DefaultMutableTreeNode(new KVP("transport_error_indicator",getTransportErrorIndicator() ,null)));
t.add(new DefaultMutableTreeNode(new KVP("payload_unit_start_indicator",getPayloadUnitStartIndicator() ,null)));
Expand Down Expand Up @@ -401,11 +397,23 @@ public DefaultMutableTreeNode getJTreeNode(final int modus) {
t.add(pesHeaderView.getJTreeNode(modus));
}
}
if(buffer.length>PAYLOAD_PACKET_LENGTH){
t.add(new DefaultMutableTreeNode(new KVP("FEC/timestamp",buffer,PAYLOAD_PACKET_LENGTH ,buffer.length - PAYLOAD_PACKET_LENGTH, null)));
}
}
return t;
}

protected String buildNodeLabel() {
final StringBuilder l = new StringBuilder("transport_packet [").append(packetNo).append("]");
if((getAdaptationFieldControl()==2)||(getAdaptationFieldControl()==3)) { //Adaptation field present
l.append(" (adaptation field)");
}
if(hasPayload()) { //payload present
l.append(" (payload)");
}
if(isPayloadUnitStartIndicator()){
l.append(" (payload start)");
}

final String nodeLabel = l.toString();
return nodeLabel;
}

public long getPacketOffset() {
Expand Down
Loading
Loading