summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Hanisch <dvb@flensrocker.de>2010-09-01 22:21:20 +0200
committerLars Hanisch <dvb@flensrocker.de>2010-09-01 22:21:20 +0200
commit7d883169bff854700e5263730ac7b319eb98da30 (patch)
tree2aa8280307efaceab16cc5cb5e47c0703fab8b9c
parent0304b3afd8ce7a9cc4fad9aa079c28829a8bc8c3 (diff)
downloadvdr-plugin-pvrinput-7d883169bff854700e5263730ac7b319eb98da30.tar.gz
vdr-plugin-pvrinput-7d883169bff854700e5263730ac7b319eb98da30.tar.bz2
integrated refactoring of teletext handling by wirbel
The former implementation seemed to loose the one or other teletext packet.
-rwxr-xr-xdevice.c2
-rwxr-xr-xpvrinput.c2
-rwxr-xr-xreader.c423
3 files changed, 206 insertions, 221 deletions
diff --git a/device.c b/device.c
index 7637579..3e4d5c4 100755
--- a/device.c
+++ b/device.c
@@ -647,7 +647,7 @@ bool cPvrDevice::SetVBImode(int vbiLinesPerFrame, int vbistatus)
return false;
}
if ((ctrl.value == V4L2_MPEG_STREAM_VBI_FMT_IVTV) && (vbiLinesPerFrame == 625)) {
- vbifmt.fmt.sliced.service_set = V4L2_SLICED_TELETEXT_B | V4L2_SLICED_WSS_625 | V4L2_SLICED_VPS;
+ vbifmt.fmt.sliced.service_set = V4L2_SLICED_VBI_625;
vbifmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
vbifmt.fmt.sliced.reserved[0] = 0;
vbifmt.fmt.sliced.reserved[1] = 0;
diff --git a/pvrinput.c b/pvrinput.c
index 74ebde6..5c9b81d 100755
--- a/pvrinput.c
+++ b/pvrinput.c
@@ -6,7 +6,7 @@
#endif
#endif
-static const char *VERSION = "2010-09-01";
+static const char *VERSION = "2010-09-02";
static const char *DESCRIPTION = tr("use Hauppauge PVR as input device");
static const char *MAINMENUENTRY = tr("PVR picture settings");
diff --git a/reader.c b/reader.c
index 3609dce..59829f3 100755
--- a/reader.c
+++ b/reader.c
@@ -1,14 +1,25 @@
#include "common.h"
#include <libsi/si.h>
+#define _fourcc(p) (uint32_t) v4l2_fourcc(*(p), *(p+1), *(p+2), *(p+3))
+
+#define TS_HEADER(_PID, _PES_HDR, _COUNTER, _ADAPTATION_CTRL) ts_buffer[0] = TS_SYNC_BYTE; \
+ ts_buffer[1] = (_PES_HDR ? 0x40:0) | (_PID >> 8); \
+ ts_buffer[2] = _PID & 0xFF; \
+ ts_buffer[3] = _ADAPTATION_CTRL << 4 | (_COUNTER & 0xf)
+
+#define TS_PAYLOAD 0x1
+#define TS_ADAPTATION_FIELD 0x2
+
#define SENDPATPMT_PACKETINTERVAL 500
+static const short kVideoPid = 301;
+static const short kAudioPid = 300;
+static const short kTeletextPid = 305;
+static const short kPCRPid = 101;
+static const uint32_t itv0 = v4l2_fourcc('i','t','v','0');
+static const uint32_t ITV0 = v4l2_fourcc('I','T','V','0');
-const short kVideoPid = 301;
-const short kAudioPid = 300;
-const short kTeletextPid = 305;
-const short kPCRPid = 101;
-enum eVbiFormat { vbifmt_itv0, vbifmt_ITV0 };
const unsigned char kPAT[TS_SIZE] = {
0x47, 0x40, 0x00, 0x10, 0x00, 0x00, 0xb0, 0x0d,
@@ -215,7 +226,7 @@ int cPvrReadThread::PutData(const unsigned char *Data, int Count)
void cPvrReadThread::PesToTs(uint8_t *Data, uint32_t Length)
{
uint8_t stream_id;
- bool first = true;
+ bool write_PES_hdr = true;
uint32_t i;
const short *pid = &kVideoPid;
uint8_t *counter = &video_counter;
@@ -234,10 +245,7 @@ void cPvrReadThread::PesToTs(uint8_t *Data, uint32_t Length)
}
if (pes_scr_isvalid && (stream_id != 0xBD)) { // send PCR packet but not PCR of vbi data
- ts_buffer[0] = TS_SYNC_BYTE;
- ts_buffer[1] = kPCRPid >> 8;
- ts_buffer[2] = kPCRPid & 0xFF;
- ts_buffer[3] = 0x20 | pcr_counter;
+ TS_HEADER(kPCRPid, 0, pcr_counter, TS_ADAPTATION_FIELD);
ts_buffer[4] = 0xB7;
ts_buffer[5] = 0x10;
ts_buffer[6] = (pes_scr & 0x01FE000000ull) >> 25; // 33 bits SCR base
@@ -255,29 +263,25 @@ void cPvrReadThread::PesToTs(uint8_t *Data, uint32_t Length)
}
switch (stream_id) {
- case 0xC0 ... 0xEF:
- if (stream_id < 0xE0) {
+ case 0xC0 ... 0xDF: // ISO/IEC 13818-3 or ISO/IEC 11172-3 audio.
pid = &kAudioPid;
counter = &audio_counter;
- }
- else if (parent->CurrentInputType == eRadio)
- return;
+ // fall through to video stream
+
+ case 0xE0 ... 0xEF: // ITU-T Rec. H.262 | ISO/IEC 13818-2 or ISO/IEC 11172-2 video
+ if (parent->CurrentInputType == eRadio && stream_id >= 0xE0)
+ return; // skip video in case of "FM radio only"
+
for (i = 0; i < Payload_Count; i++) {
- ts_buffer[0] = TS_SYNC_BYTE;
- ts_buffer[1] = (first ? 0x40 : 0x00) | (*pid >> 8);
- ts_buffer[2] = *pid & 0xFF;
- ts_buffer[3] = 0x10 | *counter;
+ TS_HEADER(*pid, write_PES_hdr, *counter, TS_PAYLOAD);
memcpy(ts_buffer + 4, Data + i * PayloadSize, PayloadSize);
PutData(ts_buffer, TS_SIZE);
packet_counter--;
*counter = (*counter + 1) & 15; //uint8_t
- first = false;
+ write_PES_hdr = false;
} // end: for (i = 0; i < Payload_Count; i++)
if (Payload_Rest > 0) {
- ts_buffer[0] = TS_SYNC_BYTE;
- ts_buffer[1] = (first ? 0x40 : 0x00) | (*pid >> 8);
- ts_buffer[2] = *pid & 0xFF;
- ts_buffer[3] = 0x30 | *counter;
+ TS_HEADER(*pid, write_PES_hdr, *counter, (TS_PAYLOAD | TS_ADAPTATION_FIELD));
ts_buffer[4] = PayloadSize - Payload_Rest - 1;
if (ts_buffer[4] > 0) {
ts_buffer[5] = 0x00;
@@ -287,213 +291,194 @@ void cPvrReadThread::PesToTs(uint8_t *Data, uint32_t Length)
PutData(ts_buffer, TS_SIZE);
packet_counter--;
*counter = (*counter + 1) & 15;
- first = false;
+ write_PES_hdr = false;
} // end: if (Payload_Rest > 0)
break; // end: case 0xE0..0xEF:
- case 0xBD: {
+
+ case 0xBD: { // private_stream_1 (teletext, vps, wss and closed_caption)
+ uint16_t pes_bytes = 46; // (9+36)byte PES header + 1byte data_identifier
+ uint16_t pes_mod; // number of pes bytes in last TS packet
+ uint8_t ts_bytes = 0; // number of bytes of current TS packet
v4l2_mpeg_vbi_fmt_ivtv *vbi_fmt = (v4l2_mpeg_vbi_fmt_ivtv*)(Data + 9 + Data[8]);
- eVbiFormat fmt;
- if (memcmp(vbi_fmt->magic, V4L2_MPEG_VBI_IVTV_MAGIC0, 4) == 0)
- fmt = vbifmt_itv0;
- else if (memcmp(vbi_fmt->magic, V4L2_MPEG_VBI_IVTV_MAGIC1, 4) == 0)
- fmt = vbifmt_ITV0;
- else
- return; // no known format
-
- uint16_t needed_size = 0;
- switch (fmt) {
- case vbifmt_itv0: {
- uint32_t bit = 1;
- int lm_nr = 0;
- int line_nr = 0;
- while ((lm_nr != 1) || (bit != 0x10)) {
- if (vbi_fmt->itv0.linemask[lm_nr] & bit) {
- if ((line_nr < 35) && ((vbi_fmt->itv0.line[line_nr].id == V4L2_MPEG_VBI_IVTV_TELETEXT_B)
- || (vbi_fmt->itv0.line[line_nr].id == V4L2_MPEG_VBI_IVTV_WSS_625)
- || (vbi_fmt->itv0.line[line_nr].id == V4L2_MPEG_VBI_IVTV_VPS)
- ))
- needed_size += 46;
- line_nr++;
- }
- bit <<= 1;
- if (bit == 0) {
- lm_nr++;
- bit = 1;
- }
- }
- break;
- }
- case vbifmt_ITV0: {
- if ((36 * sizeof(v4l2_mpeg_vbi_itv0_line) + 9 + Data[8] + 4) > Length)
- return; // not enough data
- for (int vbiNr = 0; vbiNr < 36; vbiNr++) {
- if ((vbi_fmt->ITV0.line[vbiNr].id == V4L2_MPEG_VBI_IVTV_TELETEXT_B)
- || (vbi_fmt->ITV0.line[vbiNr].id == V4L2_MPEG_VBI_IVTV_WSS_625)
- || (vbi_fmt->ITV0.line[vbiNr].id == V4L2_MPEG_VBI_IVTV_VPS)
- )
- needed_size += 46;
- }
- break;
- }
- }
- if (needed_size == 0)
- return; // no lines for translation
- needed_size += 46; // for PES header
- uint16_t mod = needed_size % 184;
- if (mod > 0)
- needed_size += 184 - mod; // fill the last packet with stuffing
- text_counter = (text_counter + 1) & 15;
- memset(ts_buffer, 0xFF, TS_SIZE);
- ts_buffer[0] = TS_SYNC_BYTE;
- ts_buffer[1] = 0x40 | (kTeletextPid >> 8);
- ts_buffer[2] = kTeletextPid & 0xFF;
- ts_buffer[3] = 0x10 | text_counter;
- memcpy(ts_buffer + 4, Data, 9 + Data[8]);
- ts_buffer[8] = ((needed_size - 6) >> 8) & 0xFF; // decrease by length of "00 00 01 bd xx xx"
- ts_buffer[9] = (needed_size - 6) & 0xFF;
- ts_buffer[12] = 0x24;
- ts_buffer[49] = 0x10; // data identifier for EBU data
- uint8_t ts_line_nr = 1;
- uint8_t ITV0_vbiLineNr = 0;
- uint8_t itv0_vbiLineNr = 0;
- uint32_t itv0_bit = 1;
- uint8_t itv0_linemaskNr = 0;
- uint8_t itv0_field_parity = 1;
- uint8_t itv0_line_offset = 6;
-
- uint8_t data_unit_id = 0;
- uint8_t framing_code = 0;
+ v4l2_mpeg_vbi_itv0_line *vbi_line = 0;
+ uint32_t magic = _fourcc(vbi_fmt->magic);
+ uint32_t bitmask = 0; // itv0 bitmask
+ uint32_t *linemask = NULL; // pointer to current itv0 32bit linemask.
uint8_t field_parity = 0;
uint8_t line_offset = 0;
- uint8_t copy_vbi_bytes = 0;
- uint8_t vbi_bytes[13] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- bool copy_vbi_line = false;
- v4l2_mpeg_vbi_itv0_line *vbi_line = 0;
- while (true) {
- data_unit_id = 0;
- framing_code = 0;
- field_parity = 0;
- line_offset = 0;
- copy_vbi_bytes = 0;
- copy_vbi_line = false;
- vbi_line = 0;
- switch (fmt) {
- case vbifmt_itv0: {
- if ((itv0_vbiLineNr < 35) && (vbi_fmt->itv0.linemask[itv0_linemaskNr] & itv0_bit)) {
- switch (vbi_fmt->itv0.line[itv0_vbiLineNr].id) {
- case V4L2_MPEG_VBI_IVTV_TELETEXT_B: {
- data_unit_id = 0x02;
- framing_code = 0xE4;
- copy_vbi_line = true;
- break;
- }
- case V4L2_MPEG_VBI_IVTV_WSS_625: {
- data_unit_id = 0xC4;
- framing_code = kInvTab[vbi_fmt->itv0.line[itv0_vbiLineNr].data[0]];
- vbi_bytes[0] = kInvTab[vbi_fmt->itv0.line[itv0_vbiLineNr].data[1]];
- copy_vbi_bytes = 1;
- break;
- }
- case V4L2_MPEG_VBI_IVTV_VPS: {
- data_unit_id = 0xC3;
- framing_code = kInvTab[vbi_fmt->itv0.line[itv0_vbiLineNr].data[0]];
- for (int i = 0; i < 12; i++)
- vbi_bytes[i] = kInvTab[vbi_fmt->itv0.line[itv0_vbiLineNr].data[i + 1]];
- copy_vbi_bytes = 12;
- break;
- }
- }
- if (data_unit_id != 0) {
- vbi_line = &vbi_fmt->itv0.line[itv0_vbiLineNr];
- field_parity = itv0_field_parity;
- line_offset = itv0_line_offset;
- }
- itv0_vbiLineNr++;
- }
- itv0_bit <<= 1;
- if ((itv0_linemaskNr == 0) && (itv0_bit == 0)) {
- itv0_bit = 1;
- itv0_linemaskNr++;
- }
- itv0_line_offset++;
- if (itv0_line_offset == 24) {
- itv0_field_parity = 0;
- itv0_line_offset = 6;
- }
+ uint8_t *dp = NULL;
+ uint8_t itv0_index = 0; // index 0 corresponds to the first valid bit in linemask
+
+ if ((magic != itv0) && (magic != ITV0)) {
+ log(pvrERROR,"%s %d: skipping garbage teletext data.", __FUNCTION__, __LINE__);
+ return;
+ }
+
+ // count number of valid vbi lines to calculate length of pes packet
+ itv0_index = 0;
+ bitmask = 1;
+ linemask = &vbi_fmt->itv0.linemask[0];
+ for (int line = 0; line < 36; line++) {
+ if (magic == itv0) {
+ if (line > 34) // only up to 35 lines in itv0.
break;
- }
- case vbifmt_ITV0: {
- switch (vbi_fmt->ITV0.line[ITV0_vbiLineNr].id) {
- case V4L2_MPEG_VBI_IVTV_TELETEXT_B: {
- data_unit_id = 0x02;
- framing_code = 0xE4;
- copy_vbi_line = true;
- break;
- }
- case V4L2_MPEG_VBI_IVTV_WSS_625: {
- data_unit_id = 0xC4;
- framing_code = kInvTab[vbi_fmt->ITV0.line[ITV0_vbiLineNr].data[0]];
- vbi_bytes[0] = kInvTab[vbi_fmt->ITV0.line[ITV0_vbiLineNr].data[1]];
- copy_vbi_bytes = 1;
- break;
- }
- case V4L2_MPEG_VBI_IVTV_VPS: {
- data_unit_id = 0xC3;
- framing_code = kInvTab[vbi_fmt->ITV0.line[ITV0_vbiLineNr].data[0]];
- for (int i = 0; i < 12; i++)
- vbi_bytes[i] = kInvTab[vbi_fmt->ITV0.line[ITV0_vbiLineNr].data[i + 1]];
- copy_vbi_bytes = 12;
+ if (line == 32) {
+ linemask++; // linemask[0] -> linemask[1]
+ bitmask = 1; // reinit bitmask
+ }
+ if (*linemask & bitmask) // this line found in dynamic itv0 array?
+ vbi_line = &vbi_fmt->itv0.line[itv0_index++];
+ else
+ vbi_line = NULL;
+ bitmask <<= 1;
+ }
+ else // magic == ITV0; static 36 line array of sliced vbi
+ vbi_line = &vbi_fmt->ITV0.line[line];
+
+ if (!vbi_line) continue; // itv0 and not in linemask
+
+ switch (vbi_line->id) {
+ case V4L2_MPEG_VBI_IVTV_TELETEXT_B:
+ case V4L2_MPEG_VBI_IVTV_WSS_625:
+ case V4L2_MPEG_VBI_IVTV_VPS:
+ // case V4L2_MPEG_VBI_IVTV_CAPTION_525:
+ pes_bytes += 46; // aligned to (TS_SIZE - 4)/4
break;
- }
- }
- if (data_unit_id != 0) {
- vbi_line = &vbi_fmt->ITV0.line[ITV0_vbiLineNr];
- field_parity = (ITV0_vbiLineNr < 18) ? 1 : 0;
- line_offset = (ITV0_vbiLineNr < 18) ? (ITV0_vbiLineNr + 6) : (ITV0_vbiLineNr - 12);
- }
- ITV0_vbiLineNr++;
+ default:;
+ }
+ } // end for loop
+
+ if (pes_bytes < 47)
+ return; // no payload found.
+
+ // we need to fill up n-times 184bytes. if something is left over,
+ // fill up the last packet with stuffing bytes 0xFF
+ pes_mod = pes_bytes % 184;
+ if (pes_mod > 0)
+ pes_bytes += 184 - pes_mod;
+
+ // begin of teletext PES packet. set payload start and increase counter after new TS hdr
+ TS_HEADER(kTeletextPid, 1, text_counter++, TS_PAYLOAD);
+ memcpy(&ts_buffer[4], Data, 9 + Data[8]);
+ ts_buffer[8] = (pes_bytes - 6) >> 8; // PES hdr byte 5. pes_bytes - 6 byte ('00 00 01 BD xx xx')
+ ts_buffer[9] = (pes_bytes - 6) & 0xFF; // PES hdr byte 6. pes_bytes - 6 byte ('00 00 01 BD xx xx')
+ ts_buffer[12] = 0x24; // PES hdr byte 9. PES hdr len, 0x24 -> 36 bytes PES hdr following
+ ts_buffer[49] = 0x10; // beginn payload after PES hdr, data identifier for EBU data 0x10
+ ts_bytes = 50; // 4byte hdr + 1/4 of 184 bytes payload per TS packet.
+ memset(&ts_buffer[ts_bytes], 0xFF, TS_SIZE - ts_bytes);
+
+ // prepare for copy loop
+ itv0_index = 0;
+ bitmask = 1;
+ linemask = &vbi_fmt->itv0.linemask[0];
+
+ for (int line = 0; line < 36; line++) {
+ if (magic == itv0) {
+ if (line > 34) // up to 35 lines in itv0.
break;
- }
+ if (line == 32) {
+ linemask++; // linemask[0] -> linemask[1]
+ bitmask = 1; // reinit bitmask
+ }
+ if (*linemask & bitmask) // this line found in dynamic itv0 array?
+ vbi_line = &vbi_fmt->itv0.line[itv0_index++];
+ else
+ vbi_line = NULL;
+ bitmask <<= 1;
+ }
+ else // magic == ITV0; static 36 line array of sliced vbi
+ vbi_line = &vbi_fmt->ITV0.line[line];
+
+ if (!vbi_line) continue; // itv0 and not in linemask
+
+ // itv0 is a variable length array that holds from 1 to 35 lines of sliced VBI data. The sliced VBI
+ // data lines present correspond to the bits set in the linemask array, starting from b0 of linemask[0]
+ // up through b31 of linemask[0], and from b0 of linemask[1] up through b 3 of linemask[1].
+ // line[0] corresponds to the first bit found set in the linemask array, line[1] corresponds to the
+ // second bit found set in the linemask array, etc. If no linemask array bits are set, then line[0]
+ // may contain one line of unspecified data that should be ignored by applications.
+ // NOTE: variable 'line' corresponds, if valid, to the same line_offset as in case of ITV0.
+ //
+ // v4l2 api: ITV0 line[0] through line [17] correspond to lines 6 through 23 of the first field.
+ // line[18] through line[35] corresponds to lines 6 through 23 of the second field.
+ // en301775: field_parity: "The value '1' indicates the first field of a frame; the value '0' indicates
+ // the second field of a frame."
+ // en301775 Table 5: line_offset for EBU and Inverted Teletext
+ if (line < 18) {
+ field_parity = 1;
+ line_offset = line + 6;
+ }
+ else {
+ field_parity = 0;
+ line_offset = line - 12;
+ }
+
+ dp = &ts_buffer[ts_bytes];
+
+ switch (vbi_line->id) {
+ case V4L2_MPEG_VBI_IVTV_TELETEXT_B: {
+ *(dp++) = 0x02; // data_unit_id
+ *(dp++) = 0x2C; // data_unit_length (0x2C -> 44bytes still following)
+ *(dp++) = 0xC0 | (field_parity << 5) | (line_offset & 0x1f);
+ *(dp++) = 0xE4; // framing_code 11100100 for EBU teletext, en300706
+ for (int i = 0; i < 42; i++) // 42 byte payload per line (inverse bit order); starting after Clock run-in
+ *(dp++) = kInvTab[vbi_line->data[i]];
+ ts_bytes += 46;
+ break;
}
-
- if ((vbi_line != 0) && (copy_vbi_line || copy_vbi_bytes)) {
- if (ts_line_nr == 0) { // send current packet and prepare next one
- PutData(ts_buffer, TS_SIZE);
- packet_counter--;
- text_counter = (text_counter + 1) & 15;
- memset(ts_buffer, 0xFF, TS_SIZE);
- ts_buffer[0] = TS_SYNC_BYTE;
- ts_buffer[1] = (kTeletextPid >> 8);
- ts_buffer[2] = kTeletextPid & 0xFF;
- ts_buffer[3] = 0x10 | text_counter;
- }
- ts_buffer[4 + ts_line_nr * 46 + 0] = data_unit_id;
- ts_buffer[4 + ts_line_nr * 46 + 1] = 0x2C;
- ts_buffer[4 + ts_line_nr * 46 + 2] = 0xC0 | (field_parity << 5) | (line_offset & 0x1f);
- ts_buffer[4 + ts_line_nr * 46 + 3] = framing_code;
- if (copy_vbi_line) {
- for (int datNr = 0; datNr < 42; datNr++)
- ts_buffer[4 + ts_line_nr * 46 + 4 + datNr] = kInvTab[vbi_line->data[datNr]];
- }
- else if (copy_vbi_bytes > 0) {
- for (int datNr = 0; datNr < copy_vbi_bytes; datNr++)
- ts_buffer[4 + ts_line_nr * 46 + 4 + datNr] = vbi_bytes[datNr];
- }
- ts_line_nr++;
- if (ts_line_nr == 4)
- ts_line_nr = 0;
- }
- if (((fmt == vbifmt_itv0) && (itv0_bit == 0x10) && (itv0_linemaskNr == 1))
- || ((fmt == vbifmt_ITV0) && (ITV0_vbiLineNr == 36)))
- break;
- }
- while ((ts_line_nr > 0) && (ts_line_nr < 4)) { // ts_buffer is initialized with 0xFF, so just set the data unit length for the stuffing lines
- ts_buffer[4 + ts_line_nr * 46 + 1] = 0x2C;
- ts_line_nr++;
+ case V4L2_MPEG_VBI_IVTV_WSS_625: {
+ *(dp++) = 0xC4; // data_unit_id
+ *(dp++) = 0x2C; // data_unit_length: 1byte 0xF7 + 14bit data + 0b11 reserved + 40bytes filling.
+ *(dp++) = 0xF7; // 0b11 + 1bit parity = 1 + 5bit fixed line 23
+ for (int i = 0; i < 2; i++)
+ *(dp++) = kInvTab[vbi_line->data[i]]; // 14bit data
+ ts_bytes += 46;
+ break;
+ }
+ case V4L2_MPEG_VBI_IVTV_VPS: {
+ *(dp++) = 0xC3; // data_unit_id
+ *(dp++) = 0x2C; // data_unit_length: 1byte 0xF0 + 13byte data (after Start Code) + 29bytes filling.
+ *(dp++) = 0xF0; // 0b11 + 1bit parity = 1 + 5bit fixed line 16
+ for (int i = 0; i < 13; i++)
+ *(dp++) = kInvTab[vbi_line->data[i]]; // 13bytes in inverse bit order. en300231
+ ts_bytes += 46;
+ break;
+ }
+ //case V4L2_MPEG_VBI_IVTV_CAPTION_525: {
+ // *(dp++) = 0xC5; // data_unit_id
+ // *(dp++) = 0x2C; // data_unit_length: aligned to 46bytes
+ // // what structure here?
+ // ts_bytes += 46;
+ // break;
+ // }
+ default:;
}
- PutData(ts_buffer, TS_SIZE);
+
+ if (ts_bytes >= TS_SIZE) {
+ PutData(ts_buffer, TS_SIZE); // next (4 + 4*46) byte for TS packet reached. send packet
+ TS_HEADER(kTeletextPid, 0, text_counter++, TS_PAYLOAD);
+ ts_bytes = 4; // 4bytes TS hdr size
+ memset(&ts_buffer[ts_bytes], 0xFF, TS_SIZE - ts_bytes);
+ }
+
+ } // end copy for loop
+
+ if (ts_bytes > 4) {
+ // need bit stuffing last TS packet.
+ // ts_buffer is set to 0xFF, so just set the data_unit_length for stuffing
+ for (;ts_bytes < TS_SIZE; ts_bytes += 46)
+ ts_buffer[1 + ts_bytes] = 0x2C;
+
+ PutData(ts_buffer, TS_SIZE);
+ }
break; // end: case 0xBD:
}
+
+ case 0xBE: // padding_stream
+ return;
+
+ default: // unexpected stream_id.
+ log(pvrDEBUG1,"%s: unhandled stream_id 0x%.2x", __FUNCTION__, stream_id);
} // end: switch (stream_id)
}