summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard <richard@ha-server.local>2016-12-31 16:16:32 +0000
committerRichard <richard@ha-server.local>2016-12-31 16:16:32 +0000
commit98c0f442b38ba84f759372986d7575478172fffc (patch)
treede75ff450e2b06206473bb3660165f7a1c878268
parentb55086aaf5efe6d5a6a88b96a39058f6ea55d0b0 (diff)
downloadvdr-convert-98c0f442b38ba84f759372986d7575478172fffc.tar.gz
vdr-convert-98c0f442b38ba84f759372986d7575478172fffc.tar.bz2
Genindex support for 5.1 AC3 or DTS surround sound
-rw-r--r--genindex/pes.c304
-rw-r--r--genindex/version.h7
2 files changed, 170 insertions, 141 deletions
diff --git a/genindex/pes.c b/genindex/pes.c
index c5931dd..1864988 100644
--- a/genindex/pes.c
+++ b/genindex/pes.c
@@ -8,6 +8,9 @@
*-------------------------------------------------------------------------------
* Revision History
* $Log: pes.c,v $
+ * Revision 1.4 2016/12/31 16:11:24 richard
+ * Support for 5.1 AC3 or DTS surround sound
+ *
* Revision 1.3 2016/10/01 13:32:55 richard
* Make header error non fatal
*
@@ -463,7 +466,7 @@ int cPES::Process(const uchar *data, int len)
static uchar headerstore[64];
static int savedheadersize;
static int overrun;
- static bool started;
+ static bool subsstarted;
while(used<len) {
uchar *c=(uchar *)data+used;
@@ -532,7 +535,8 @@ int cPES::Process(const uchar *data, int len)
continue;
}
// no sync found, move buffer one position ahead
- have--; Skip(hbuff);
+ have--;
+ Skip(hbuff);
memmove(hbuff,hbuff+1,have);
// if all bytes from previous data block used up, switch to FastSync
if(!--old) {
@@ -620,156 +624,178 @@ int cPES::Process(const uchar *data, int len)
case prAct1: n=Action1(type,c,n); break;
case prAct2: n=Action2(type,c,n); break;
// case prAct3: n=Action3(type,c,n); break;
- case prAct3:
- /* RF Because we have to assemble AN ENTIRE PES packet of possibly several existing 2k PES packets,
- and usually several subtitle segments, then as far as the long main loop is concerned,
- we drop all the subs packets regardless.
-
- VDR1.x packets can contain fragments of segments too
-
- We have no idea how long we have to wait - need END_OF_DISPLAY_SET_SEGMENT to complete a PES
- Then write out the assembled PES independently, hoping it's PTS doesn't
- upset something downstream. Should in any case be indpendent, but ffmpeg is touchy
- */
- n = -n; //drop all content for main loop
- if (-n ) {
- int PayloadOffset = headerSize;
- bool ResetSubtitleAssembler = 0;
- //VDR 1.x subs, skip special 4 byte "substream header" (VDR always strips all packets)
- int SubstreamHeaderLength = (have == 0 ? 4 : 0); // Full packet, not a continuation chunk from file
- // c points to the payload only now
- if (SOP && SubstreamHeaderLength) { // only if we have it
- ResetSubtitleAssembler = c[3] == 0x00;
- //PES hdr extension, RF original doesn't match vanilla 1.X recordings
- if ((header[7] & 0x01) && (header[PayloadOffset - 3] & 0x81) == 0x01 && header[PayloadOffset - 2] == 0x81) {
- PayloadOffset--;
- SubstreamHeaderLength = 1;
- ResetSubtitleAssembler = (header[8] >= 5);
- }
- if (PesHasPts(header)) {
- int64_t oldpts = ptsnow[type];
- ptsnow[type] = PesGetPts(header);
- if (ptsnow[type] < oldpts) {
- // Non-monotonic subs send ffmpeg loopy
- printf("PES: OOPs Non-monotonic PTS at %jd (previous %jd!) - packet dropped\n",ptsnow[type],oldpts);
- break;
- }
- int64_t ptsdiff = (PtsDiff(ptsnow[0xc0],ptsnow[type]))/90; //millisecs
- DEBUG("PES: subtitle packet pts %jd, latest main audio pts %jd, subs ahead %jdms\n",ptsnow[type],ptsnow[0xc0],ptsdiff);
- if (ptsnow[0xc0] && abs((int)ptsdiff) > 5000) {
- printf("genindex: OOPs large subs timing offset! %jdms\n",ptsdiff);
- }
- if (headerSize +2 > (int)sizeof (headerstore)) {
- printf("PES: OOPs huge header! %d at %jd - packet dropped\n",headerSize,ptsnow[type]);
- break;
+ case prAct3:
+ // first deal with AC3 / DTS
+ n=Action1(type,c,n); // don't scan output
+ int PayloadOffset;
+ PayloadOffset = headerSize;
+ //PES hdr extension, from dvbsubtitle.c, Compatibility mode for old subtitles plugin (doesn't match vanilla 1.X recordings)
+ if ((header[7] & 0x01) && (header[PayloadOffset - 3] & 0x81) == 0x01 && header[PayloadOffset - 2] == 0x81) {
+ PayloadOffset--;
+ }
+ if (header[PayloadOffset] != 0x20) { // assume AC3 or DTS
+ // VDR has the PES "DVD" substream header like 80 01 00 01 to identify the stream
+ // this confuses ffmpeg in a .ts, so strip it at SOP. sse http://stnsoft.com/DVD/ass-hdr.html
+ if (SOP) {
+ used+=4;
+ n-=4;
+ payloadSize-=4; //dummy it up so we don't overstep
+ ModifyPaketSize(-4); //actually truncate rewritten stream also
+ Skip(c,4);
+ }
+ break; // passthrough
+ } else {
+ /* Subtitles stream
+ Because we have to assemble AN ENTIRE PES packet of possibly several existing 2k PES packets,
+ and usually several subtitle segments, then as far as the long main loop is concerned,
+ we drop all the subs packets.
+
+ VDR1.x packets can contain fragments of segments too
+
+ We have no idea how long we have to wait - need END_OF_DISPLAY_SET_SEGMENT to complete a PES
+ Then write out the assembled PES independently, hoping it's PTS doesn't
+ upset something downstream. Should in any case be indpendent, but ffmpeg is touchy
+ */
+ n = -n; //drop all content for main loop
+ if (-n) {
+ PayloadOffset = headerSize;
+ bool ResetSubtitleAssembler = 0;
+ //VDR 1.x subs, skip special 4 byte "substream header" (VDR always strips all packets)
+ int SubstreamHeaderLength = (have == 0 ? 4 : 0); // Full packet, not a continuation chunk from file
+ // c points to the payload only now
+ if (SOP && SubstreamHeaderLength) { // only if we have it
+ ResetSubtitleAssembler = c[3] == 0x00;
+ //PES hdr extension, from dvbsubtitle.c, Compatibility mode for old subtitles plugin (doesn't match vanilla 1.X recordings)
+ if ((header[7] & 0x01) && (header[PayloadOffset - 3] & 0x81) == 0x01 && header[PayloadOffset - 2] == 0x81) {
+ PayloadOffset--;
+ SubstreamHeaderLength = 1;
+ ResetSubtitleAssembler = (header[8] >= 5); // i.e. there's a header extension
}
- if (overrun) { // continuation packets don't have a PTS AFAIK
- DEBUG("PES: Suspect %d bytes left at start of new packet!\n",overrun);
- }
-
- memcpy (headerstore,header,headerSize);
- headerstore[6] |= 0x01; // Set "Original" - per trouble-free .ts FWiW
-
-// if (audiopts) PesSetPts(headerstore,audiopts); // use existing if no audiopts
+ if (PesHasPts(header)) {
+ int64_t oldpts = ptsnow[type];
+ ptsnow[type] = PesGetPts(header);
+ if (ptsnow[type] < oldpts) {
+ // Non-monotonic subs send ffmpeg loopy
+ printf("PES: OOPs Non-monotonic PTS at %jd (previous %jd!) - packet dropped\n",ptsnow[type],oldpts);
+ break;
+ }
+ int64_t ptsdiff = (PtsDiff(ptsnow[0xc0],ptsnow[type]))/90; //millisecs
+ DEBUG("PES: subtitle packet pts %jd, latest main audio pts %jd, subs ahead %jdms\n",ptsnow[type],ptsnow[0xc0],ptsdiff);
+ if (ptsnow[0xc0] && abs((int)ptsdiff) > 5000) {
+ printf("genindex: OOPs large subs timing offset! %jdms\n",ptsdiff);
+ }
+ if (headerSize +2 > (int)sizeof (headerstore)) {
+ printf("PES: OOPs huge header! %d at %jd - packet dropped\n",headerSize,ptsnow[type]);
+ break;
+ }
+ if (overrun) { // continuation packets don't have a PTS AFAIK
+ DEBUG("PES: Suspect %d bytes left at start of new packet!\n",overrun);
+ }
+
+ memcpy (headerstore,header,headerSize);
+ headerstore[6] |= 0x01; // Set "Original" - per trouble-free .ts FWiW
+
+ // if (audiopts) PesSetPts(headerstore,audiopts); // use existing if no audiopts
+
+ // Working on theory that ffmpeg wants a DTS for some reason, copy the PTS
+ // - it turns out that ffmpeg does this internally.
+ // PesSetDtsbit(headerstore);
+ // PesSetDts(headerstore,ptsnow[type]-18000); // ~200ms earlier similar to other streams
+ // headerstore[8]+=5; // 5 for DTS (we know it has PES ext:this is safe)
-// Working on theory that ffmpeg wants a DTS for some reason, copy the PTS
-// - it turns out that ffmpeg does this internally.
-// PesSetDtsbit(headerstore);
-// PesSetDts(headerstore,ptsnow[type]-18000); // ~200ms earlier similar to other streams
-// headerstore[8]+=5; // 5 for DTS (we know it has PES ext:this is safe)
-
- savedheadersize = headerSize+2+0; // 5 for DTS
- memset (headerstore+headerSize+0,0x20,1); // subs data_identifier which is stripped below
- memset (headerstore+headerSize+1+0,0x00,1); // stream_id
+ savedheadersize = headerSize+2+0; // 5 for DTS
+ memset (headerstore+headerSize+0,0x20,1); // subs data_identifier which is stripped below
+ memset (headerstore+headerSize+1+0,0x00,1); // stream_id
+ }
}
- }
- if (-n > SubstreamHeaderLength) {
- const uchar *data = c + SubstreamHeaderLength; // skip substream header
- int length = -n - SubstreamHeaderLength; // skip substream header
- if (ResetSubtitleAssembler) {
- dvbSubtitleAssembler->Reset();
- }
- if (length > 3) {
- int Count, offset;
- int substotalthispacket=0;
- if (data[0] == 0x20 && data[1] == 0x00 && data[2] == 0x0F) {
- offset = 2;
- } else {
- offset = 0;
+ if (-n > SubstreamHeaderLength) {
+ const uchar *data = c + SubstreamHeaderLength; // skip substream header
+ int length = -n - SubstreamHeaderLength; // skip substream header
+ if (ResetSubtitleAssembler) {
+ dvbSubtitleAssembler->Reset();
}
- int subslength = length - offset;
- DEBUG("PES: Put payload length %d into dvbSubtitleAssembler\n",subslength);
- dvbSubtitleAssembler->Put(data + offset, subslength);
- while (true) {
- unsigned char *b = dvbSubtitleAssembler->Get(Count); // Count = seg size *req'd*, not actual available!
- if (b && b[0] == 0x0F && Count > 5) {
- // a complete segement
- uchar segmentType = b[1];
- if (segmentType == STUFFING_SEGMENT) {
- continue;
- }
- if (fifo_write(&fifo, b, Count) != Count) {
- DEBUG("PES: FIFO error\n");
- Return(used,len);
- }
- substotalthispacket+=Count-overrun;
- size+=Count;
- DEBUG("PES: subtitle complete segment length %d type %02X, subs in fifo %d (used %d this segment)\n",Count, segmentType, size, Count-overrun);
- if (Count-overrun < 0) {
- DEBUG("PES: Suspect overrun of %d bytes!\n",overrun);
- }
- overrun=0; // must have used up all available data at start ofa new segment
-
- if (segmentType == END_OF_DISPLAY_SET_SEGMENT) {
- uchar outbuf[KILOBYTE(64)];
- if (fifo_read(&fifo, outbuf, size) != size) {
+ if (length > 3) {
+ int Count, offset;
+ int substotalthispacket=0;
+ if (data[0] == 0x20 && data[1] == 0x00 && data[2] == 0x0F) {
+ offset = 2;
+ } else {
+ offset = 0;
+ }
+ int subslength = length - offset;
+ DEBUG("PES: Put payload length %d into dvbSubtitleAssembler\n",subslength);
+ dvbSubtitleAssembler->Put(data + offset, subslength);
+ while (true) {
+ unsigned char *b = dvbSubtitleAssembler->Get(Count); // Count = seg size *req'd*, not actual available!
+ if (b && b[0] == 0x0F && Count > 5) {
+ // a complete segement
+ uchar segmentType = b[1];
+ if (segmentType == STUFFING_SEGMENT) {
+ continue;
+ }
+ if (fifo_write(&fifo, b, Count) != Count) {
DEBUG("PES: FIFO error\n");
- Return(used,len);
+ Return(used,len);
}
- // skip the small 10...80 subs periodic "cleardown" packets at beginning of file only.
- // These currently prevent reliable ffmpeg subs detection
- int err = dvbsub_probe(outbuf,size,ptsnow[type]);
- if (err == 1) started = 1;
- if (started) {
- if (err < 0 ) errpkts++; // mark it, but pass all the same as should be validly assembled
- outbuf[size++] = 0xff; // end_of_PES_data_field_marker
- totsubsize+=size; // Actual subs segment data = should match ffmpeg report
- subspkts+=1;
- int pkt = savedheadersize -6 + size; //6 for 00.00.01.bd.HH.hh, 1 for end_of_PES_data_field_marker
- headerstore[4]=(pkt>>8)&0xFF;
- headerstore[5]=(pkt )&0xFF;
- // Now can output ALL re-assembled subs in a SINGLE PES pkt
- DEBUG("PES: *** subtitle complete PES packet with subs of %d bytes @pts %jd ***\n",size, ptsnow[type]);
- PD("PES: output buffered subtitle header=%p count=%d\n",headerstore,savedheadersize);
- int r=Output(headerstore,savedheadersize);
- if(r<0) return Return(-1,len);
- PD("PES: output buffered subtitle count=%d\n",size);
- r=Output(outbuf,size);
- if(r<0) return Return(-1,len);
- } else {
- DEBUG("PES: Skipping inital short subs packet for ffmpeg compatibility!\n");
+ substotalthispacket+=Count-overrun;
+ size+=Count;
+ DEBUG("PES: subtitle complete segment length %d type %02X, subs in fifo %d (used %d this segment)\n",Count, segmentType, size, Count-overrun);
+ if (Count-overrun < 0) {
+ DEBUG("PES: Suspect overrun of %d bytes!\n",overrun);
}
- size = 0;
- }
- } else {
- if (Count > subslength - substotalthispacket) {
-// if (c[SubstreamHeaderLength+offset+substotalthispacket] == 0xff) {
- if (subslength - substotalthispacket < 6) { //cruft or stuffing
- break;
+ overrun=0; // must have used up all available data at start of a new segment
+
+ if (segmentType == END_OF_DISPLAY_SET_SEGMENT) {
+ uchar outbuf[KILOBYTE(64)];
+ if (fifo_read(&fifo, outbuf, size) != size) {
+ DEBUG("PES: FIFO error\n");
+ Return(used,len);
+ }
+ // skip the small 10...80 subs periodic "cleardown" packets at beginning of file only.
+ // These currently prevent reliable ffmpeg subs detection
+ int err = dvbsub_probe(outbuf,size,ptsnow[type]);
+ if (err == 1) subsstarted = 1;
+ if (subsstarted) {
+ if (err < 0 ) errpkts++; // mark it, but pass all the same as should be validly assembled
+ outbuf[size++] = 0xff; // end_of_PES_data_field_marker
+ totsubsize+=size; // Actual subs segment data = should match ffmpeg report
+ subspkts+=1;
+ int pkt = savedheadersize -6 + size; //6 for 00.00.01.bd.HH.hh, 1 for end_of_PES_data_field_marker
+ headerstore[4]=(pkt>>8)&0xFF;
+ headerstore[5]=(pkt )&0xFF;
+ // Now can output ALL re-assembled subs in a SINGLE PES pkt
+ DEBUG("PES: *** subtitle complete PES packet with subs of %d bytes @pts %jd ***\n",size, ptsnow[type]);
+ PD("PES: output buffered subtitle header=%p count=%d\n",headerstore,savedheadersize);
+ int r=Output(headerstore,savedheadersize);
+ if(r<0) return Return(-1,len);
+ PD("PES: output buffered subtitle count=%d\n",size);
+ r=Output(outbuf,size);
+ if(r<0) return Return(-1,len);
+ } else {
+ DEBUG("PES: Skipping inital short subs packet for ffmpeg compatibility!\n");
+ }
+ size = 0;
}
- // overrun the PES packet. Keep building packet with next PES segement.
- overrun += subslength - substotalthispacket;
- DEBUG("PES: subtitle incomplete segment, requires %d vs. %d available (needs %d)\n",Count, overrun, Count-overrun);
- if (overrun < 0) {
- printf("PES: BUG! Available %d bytes, @pts %jd ***\n",overrun, ptsnow[type]);
- exit (1);
+ } else {
+ if (Count > subslength - substotalthispacket) {
+ // if (c[SubstreamHeaderLength+offset+substotalthispacket] == 0xff) {
+ if (subslength - substotalthispacket < 6) { //cruft or stuffing
+ break;
+ }
+ // overrun the PES packet. Keep building packet with next PES segement.
+ overrun += subslength - substotalthispacket;
+ DEBUG("PES: subtitle incomplete segment, requires %d vs. %d available (needs %d)\n",Count, overrun, Count-overrun);
+ if (overrun < 0) {
+ printf("PES: BUG! Available %d bytes, @pts %jd ***\n",overrun, ptsnow[type]);
+ exit (1);
+ }
}
+ break;
}
- break;
}
+ // We have a complete disassembly of the sub(s)
}
- // We have a complete disassembly of the sub(s)
}
}
}
diff --git a/genindex/version.h b/genindex/version.h
index 7de58b0..8e99b5a 100644
--- a/genindex/version.h
+++ b/genindex/version.h
@@ -22,6 +22,9 @@
*-------------------------------------------------------------------------------
* Revision History
* $Log: version.h,v $
+ * Revision 1.4 2016/12/31 16:11:24 richard
+ * Support for 5.1 AC3 or DTS surround sound
+ *
* Revision 1.3 2016/10/01 13:36:07 richard
* Make header error non fatal
*
@@ -36,8 +39,8 @@
#define ___VERSION_H
#define PRG_NAME "genindex"
-#define PRG_VERSION "0.2.1"
+#define PRG_VERSION "0.2.2"
#endif //___VERSION_H
-// --------- $Id: version.h,v 1.3 2016/10/01 13:36:07 richard Exp $ ---------- END \ No newline at end of file
+// --------- $Id: version.h,v 1.4 2016/12/31 16:11:24 richard Exp $ ---------- END \ No newline at end of file