1 #include <lib/dvb/pvrparse.h>
2 #include <lib/base/eerror.h>
5 #error no byte order defined!
8 int eMPEGStreamInformation::save(const char *filename
)
10 FILE *f
= fopen(filename
, "wb");
14 for (std::map
<off_t
, Timestamp
>::const_iterator
i(accessPoints
.begin()); i
!= accessPoints
.end(); ++i
)
16 unsigned long long d
[2];
17 #if BYTE_ORDER == BIG_ENDIAN
21 d
[0] = bswap64(i
->first
);
22 d
[1] = bswap64(i
->second
);
24 fwrite(d
, sizeof(d
), 1, f
);
31 int eMPEGStreamInformation::load(const char *filename
)
33 FILE *f
= fopen(filename
, "rb");
39 unsigned long long d
[2];
40 if (fread(d
, sizeof(d
), 1, f
) < 1)
43 #if BYTE_ORDER == LITTLE_ENDIAN
47 accessPoints
[d
[0]] = d
[1];
50 fixupDiscontinuties();
54 eMPEGStreamInformation::operator bool()
56 return !!accessPoints
.size();
59 void eMPEGStreamInformation::fixupDiscontinuties()
61 timestampDeltas
.clear();
62 if (!accessPoints
.size())
65 eDebug("Fixing discontinuities ...");
66 Timestamp currentDelta
= accessPoints
.begin()->second
, lastTimestamp
= 0;
67 timestampDeltas
[accessPoints
.begin()->first
] = accessPoints
.begin()->second
;
68 for (std::map
<off_t
,Timestamp
>::const_iterator
i(accessPoints
.begin()); i
!= accessPoints
.end(); ++i
)
70 Timestamp current
= i
->second
- currentDelta
;
71 Timestamp diff
= current
- lastTimestamp
;
72 if (diff
> (90000*5)) // 5sec diff
74 eDebug("%llx < %llx, have discont. new timestamp is %llx (diff is %llx)!", current
, lastTimestamp
, i
->second
, diff
);
75 currentDelta
= i
->second
- lastTimestamp
;
76 eDebug("current delta now %llx, making current to %llx", currentDelta
, i
->second
- currentDelta
);
77 timestampDeltas
[i
->first
] = currentDelta
;
79 lastTimestamp
= i
->second
- currentDelta
;
81 eDebug("ok, found %d disconts.", timestampDeltas
.size());
84 eMPEGStreamInformation::Timestamp
eMPEGStreamInformation::getDelta(eMPEGStreamInformation::off_t offset
)
86 if (!timestampDeltas
.size())
88 std::map
<off_t
,Timestamp
>::iterator i
= timestampDeltas
.upper_bound(offset
);
90 /* i can be the first when you query for something before the first PTS */
91 if (i
!= timestampDeltas
.begin())
97 eMPEGStreamInformation::Timestamp
eMPEGStreamInformation::getInterpolated(eMPEGStreamInformation::off_t offset
)
99 /* get the PTS values before and after the offset. */
100 std::map
<off_t
,Timestamp
>::iterator before
, after
;
102 after
= accessPoints
.upper_bound(offset
);
105 eDebug("query %llx", offset
);
107 if (before
!= accessPoints
.begin())
109 else /* we query before the first known timestamp ... FIXME */
111 eDebug("query before");
116 if (before
== accessPoints
.end())
122 /* if after == end, then we need to extrapolate ... FIXME */
123 if ((before
->first
== offset
) || (after
== accessPoints
.end()))
125 eDebug("exact match (or after end..)");
126 return before
->second
- getDelta(offset
);
129 Timestamp before_ts
= before
->second
- getDelta(before
->first
);
130 Timestamp after_ts
= after
->second
- getDelta(after
->first
);
132 Timestamp diff
= after_ts
- before_ts
;
133 off_t diff_off
= after
->first
- before
->first
;
134 eDebug("interpolating: %llx(%llx) .. %llx .. %llx(%llx)", before
->first
, before_ts
, offset
, after
->first
, after_ts
),
136 diff
= (offset
- before
->first
) * diff
/ diff_off
;
137 eDebug("result %llx + %llx = %llx", before_ts
, diff
, before_ts
+ diff
);
138 return before_ts
+ diff
;
141 eMPEGStreamInformation::off_t
eMPEGStreamInformation::getAccessPoint(eMPEGStreamInformation::Timestamp ts
)
143 /* FIXME: more efficient implementation */
146 for (std::map
<off_t
, Timestamp
>::const_iterator
i(accessPoints
.begin()); i
!= accessPoints
.end(); ++i
)
148 std::map
<off_t
, Timestamp
>::const_iterator d
= timestampDeltas
.find(i
->first
);
149 if (d
!= timestampDeltas
.end())
151 Timestamp c
= i
->second
- delta
;
159 eMPEGStreamParserTS::eMPEGStreamParserTS(eMPEGStreamInformation
&streaminfo
): streaminfo(streaminfo
), pktptr(0), pid(-1), needNextPacket(0), skip(0)
163 int eMPEGStreamParserTS::processPacket(const unsigned char *pkt
, eMPEGStreamInformation::off_t offset
)
165 if (!wantPacket(pkt
))
166 printf("ne irgendwas ist da falsch\n");
168 const unsigned char *end
= pkt
+ 188;
170 if (!(pkt
[3] & 0x10))
172 eWarning("[TSPARSE] PUSI set but no payload.");
176 if (pkt
[3] & 0x20) // adaption field present?
177 pkt
+= pkt
[4] + 4 + 1; /* skip adaption field and header */
179 pkt
+= 4; /* skip header */
183 eWarning("[TSPARSE] dropping huge adaption field");
187 // ok, we now have the start of the payload, aligned with the PES packet start.
188 if (pkt
[0] || pkt
[1] || (pkt
[2] != 1))
190 eWarning("broken startcode");
195 eMPEGStreamInformation::Timestamp pts
= 0;
198 if (pkt
[7] & 0x80) // PTS present?
200 pts
= ((unsigned long long)(pkt
[ 9]&0xE)) << 29;
201 pts
|= ((unsigned long long)(pkt
[10]&0xFF)) << 22;
202 pts
|= ((unsigned long long)(pkt
[11]&0xFE)) << 14;
203 pts
|= ((unsigned long long)(pkt
[12]&0xFF)) << 7;
204 pts
|= ((unsigned long long)(pkt
[13]&0xFE)) >> 1;
208 int sec
= pts
/ 90000;
209 int frm
= pts
% 90000;
217 eDebug("pts: %016llx %d:%02d:%02d:%02d:%05d", pts
, d
, hr
, min
, sec
, frm
);
221 /* advance to payload */
224 /* if startcode found */
225 if (!(pkt
[0] || pkt
[1] || (pkt
[2] != 1)))
227 if (pkt
[3] == 0xb3) /* sequence header */
231 streaminfo
.accessPoints
[offset
] = pts
;
232 eDebug("Sequence header at %llx, pts %llx", offset
, pts
);
234 eDebug("Sequence header but no valid PTS value.");
240 inline int eMPEGStreamParserTS::wantPacket(const unsigned char *hdr
) const
244 eDebug("missing sync!");
247 int ppid
= ((hdr
[1]&0x1F) << 8) | hdr
[2];
252 if (needNextPacket
) /* next packet (on this pid) was required? */
255 if (hdr
[1] & 0x40) /* pusi set: yes. */
261 void eMPEGStreamParserTS::parseData(eMPEGStreamInformation::off_t offset
, const void *data
, unsigned int len
)
263 const unsigned char *packet
= (const unsigned char*)data
;
264 const unsigned char *packet_start
= packet
;
266 /* sorry for the redundant code here, but there are too many special cases... */
271 /* skip last packet */
274 unsigned int skiplen
= -pktptr
;
281 } else if (pktptr
< 4) /* header not complete, thus we don't know if we want this packet */
283 unsigned int storelen
= 4 - pktptr
;
286 memcpy(pkt
+ pktptr
, packet
, storelen
);
293 if (!wantPacket(pkt
))
302 /* otherwise we complete up to the full packet */
303 unsigned int storelen
= 188 - pktptr
;
306 memcpy(pkt
+ pktptr
, packet
, storelen
);
313 needNextPacket
= processPacket(pkt
, offset
+ (packet
- packet_start
));
316 } else if (len
>= 4) /* if we have a full header... */
318 if (wantPacket(packet
)) /* decide wheter we need it ... */
320 if (len
>= 188) /* packet complete? */
322 needNextPacket
= processPacket(packet
, offset
+ (packet
- packet_start
)); /* process it now. */
325 memcpy(pkt
, packet
, len
); /* otherwise queue it up */
334 else if (!pktptr
) /* we dont want this packet, otherwise pktptr = sk (=len) > 4 */
339 } else /* if we don't have a complete header */
341 memcpy(pkt
, packet
, len
); /* complete header next time */
349 void eMPEGStreamParserTS::setPid(int _pid
)