1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
#include <stdint.h>
#include <stdlib.h>
#include <vdr/vdrttxtsubshooks.h>
#include <vdr/device.h>
#include <vdr/channels.h>
#include <vdr/receiver.h>
#include <vdr/ringbuffer.h>
#include "siinfo.h"
#include "ttxtsubsfilter.h"
#include "ttxtsubsrecorder.h"
#include "ttxtsubsreceiver.h"
#include "ttxtsubs.h"
#include "teletext.h"
#define MAXPACKETSIZE 20000
// ----- cTtxtSubsRecorder -----
cTtxtSubsRecorder::cTtxtSubsRecorder(cDevice *dev, const cChannel *ch, char *lang, int HI)
:
mDev(dev),
mSid(ch->Sid()),
mVid(ch->Vpid()),
mTtxtinfo(NULL),
mReceiver(NULL),
mPacketBuffer(NULL)
{
mTtxtinfo = (struct ttxtinfo *) malloc(sizeof(*mTtxtinfo));
struct ttxtpidinfo *pi = NULL;
int pid, page;
if(GetTtxtInfo(dev->DeviceNumber(), ch->Sid(), ch->Vpid(), mTtxtinfo)) {
fprintf(stderr, "cTtxtSubsRecorder::cTtxtSubsRecorder: GetTtxtSubtitleInfo error!\n");
} else {
pi = FindSubs(mTtxtinfo, lang, HI, &pid, &page);
if(!pi && mTtxtinfo->pidcount > 0) {
pi = &(mTtxtinfo->p[0]);
fprintf(stderr, "Selected language not found, just recording first teletext pid found.\n");
}
if(pi) {
mReceiver = new cTtxtSubsReceiver(ch->Ca(), pi);
mPacketBuffer = (uint8_t *) malloc(MAXPACKETSIZE);
} else {
fprintf(stderr, "No teletext pid found, not recording any (obviously).\n");
}
}
}
cTtxtSubsRecorder::~cTtxtSubsRecorder(void)
{
if(mReceiver) {
delete mReceiver;
mReceiver = NULL;
}
if(mTtxtinfo) {
FreeTtxtInfoData(mTtxtinfo);
free(mTtxtinfo);
}
if(mPacketBuffer)
free(mPacketBuffer);
}
uint8_t *cTtxtSubsRecorder::GetPacket(uint8_t **outbuf, size_t *lenp)
{
int done = 0;
size_t len;
uint8_t *b = (uint8_t *) mPacketBuffer;
uint8_t line[46];
*outbuf = NULL;
if(!mReceiver)
return *outbuf;
len = 46; // skip PES header area
if(mReceiver->Get(line)) {
// if first line is a Y0, insert an index page
// XXX This isn't really correct, we don't know if there is parallel magazine
// transmission and a page in the index pages' mag is in progress...
int mp;
//int mag; // X in ETSI EN 300 706
int packet; // Y
struct ttxt_data_field *d = (struct ttxt_data_field *) line;
mp = UNHAM_INV(d->mag_addr_ham[0], d->mag_addr_ham[1]);
//mag = mp & 0x7;
packet = (mp >> 3) & 0x1f;
if(packet == 0) {
char **iplines;
int iplcount;
mReceiver->IndexPage(&iplines, &iplcount);
for(int i = 0; i < iplcount; i++) {
memcpy(b + len, (char *) iplines[i], 46);
len += 46;
}
}
// insert the line
memcpy(b + len, line, 46);
len += 46;
}
// get the rest of the lines
while((len < (MAXPACKETSIZE - 184)) && !done) {
if(mReceiver->Get(b + len)) {
len += 46;
} else
done = 1;
}
if(len > 46) { // we have data, make a PES packet according to ETSI EN 300 472
// fill out packet with stuffing data to 184 byte boundary
size_t stufflen = 184 - (len % 184);
if(stufflen == 184)
stufflen = 0;
memset((char *) b + len, 0xff, stufflen);
len += stufflen;
// fill in header
uint8_t header[] = {0x00, 0x00, 0x01, 0xbd, // private data stream 1
0x00, 0x00, // len
0x80, // 10 and flags
0x00, // PTS_DTS_flags and other flags
0x24}; // PES_header_data_length
memcpy((char *) b, (char *) header, sizeof(header));
b[4] = (len-6) >> 8;
b[5] = (len-6) & 0xff;
memset((char *) b + sizeof(header), 0xff, 45 - sizeof(header)); // add stuffing bytes
b[45] = 0x1f; // EBU data, our payload type to indicate we have filtered data
*outbuf = b;
*lenp = len;
}
#if 0
if(*outbuf) { // XXX
fprintf(stderr, "cTtxtSubsRecorder::GetPacket: len: %d\n", len);
for(size_t i = 46; i < len; i +=46) {
struct ttxt_data_field *d = (struct ttxt_data_field *) b + i;
if(d->data_unit_id != 0xff)
print_line((char *) b + i);
}
}
#endif
return *outbuf;
}
void cTtxtSubsRecorder::DeviceAttach(void)
{
if(mReceiver)
mDev->AttachReceiver(mReceiver);
}
|