[ANNOUNCE] H.264 updates for VDR-1.5.9
Commit Message
Hi,
the attached vdr-1.5.9-h264.patch adds H.264 support to VDR's remuxer.
The changes to earlier releases are:
- H264::cParser has been enhanced to provide information for
H264::cContext::GetFramesPerSec() and therefore outsourced
into separate files.
- cVideoRepacker generates Access Unit Delimiters in case they
are not part of the stream.
These changes should make VDR ready for the upcoming IFA fair in regard
to the broadcasts on the temporary channel EinsFestival HD.
The other attached patch vdr-1.5.9-framespersec.patch tries to replace
the macro FRAMESPERSEC by a function call GetFramesPerSec() which
analyses a recordings first video frame to determine frames per second
which are used to calculated a recordings length. The changes to earlier
releases are:
- add support for H.264 recordings by making use of the above
mentioned H264::cParser, as frame timing stuff is quite complex.
H.264 support can be turned off by putting a comment around the
macro ADD_H264_SUPPORT in tools.c.
This change provides correct recording length reports for recordings
taken on EinsFestival HD as this channel broadcasts 50p, i. e. without
the patch, VDR will report recording times which are twice the actual time.
The patch in general may especially be useful for people with PAL and
NTSC recordings, as in this scenario it was never possible to find a
single setting for FRAMESPERSEC.
Although FRAMESPERSEC has been replaced on many locations, it is still
used to read/write cutting marks file, to stay compatible.
Have fun while expecting the next vdr-xine-release ;-)
Bye.
Comments
Reinhard Nissl wrote:
> Hi,
>
> the attached vdr-1.5.9-h264.patch adds H.264 support to VDR's remuxer.
> The changes to earlier releases are:
>
> - H264::cParser has been enhanced to provide information for
> H264::cContext::GetFramesPerSec() and therefore outsourced
> into separate files.
> - cVideoRepacker generates Access Unit Delimiters in case they
> are not part of the stream.
Should this patch make it possible to record H.264 encoded stream? I
have applied the patch and can see in the channels menu that Canal+ HD
Film uses H.264 codec, but I can not record the channel (nor watch it...).
-Petri
Hi,
Petri Helin wrote:
>> the attached vdr-1.5.9-h264.patch adds H.264 support to VDR's remuxer.
>> The changes to earlier releases are:
>>
>> - H264::cParser has been enhanced to provide information for
>> H264::cContext::GetFramesPerSec() and therefore outsourced
>> into separate files.
>> - cVideoRepacker generates Access Unit Delimiters in case they
>> are not part of the stream.
>
> Should this patch make it possible to record H.264 encoded stream? I
It should. It works for the German DVB-S2 HD channels on Astra and it
worked for LuxeTV HD on Hotbird in the past.
> have applied the patch and can see in the channels menu that Canal+ HD
> Film uses H.264 codec, but I can not record the channel (nor watch it...).
Is this the channel you've mentioned (I've applied a DVB-S2 patch, so
the entry may differ from your's a little)?
CANAL+ FILM
HD;Harmonic:11470:vC56M2S0Z0:S13.0E:27500:10331+331:332=pol;333=ORY:551:100:15423:318:1400:0
On my system, VDR says this channel is encrypted. Do you have the
necessary means to receive this channel?
Bye.
On Wed, Aug 29, 2007 at 11:38:39PM +0300, Petri Helin wrote:
> Reinhard Nissl wrote:
> > Hi,
> >
> > the attached vdr-1.5.9-h264.patch adds H.264 support to VDR's remuxer.
> > The changes to earlier releases are:
> >
> > - H264::cParser has been enhanced to provide information for
> > H264::cContext::GetFramesPerSec() and therefore outsourced
> > into separate files.
> > - cVideoRepacker generates Access Unit Delimiters in case they
> > are not part of the stream.
>
> Should this patch make it possible to record H.264 encoded stream? I
> have applied the patch and can see in the channels menu that Canal+ HD
> Film uses H.264 codec, but I can not record the channel (nor watch it...).
>
> -Petri
I did apply this h264 patch and streamdev patch from:
http://www.vdr-developer.org/mantisbt/view.php?id=382
Now the load of the server is low when tuned to Canal+ HD and I can watch the stream using vlc.
The recording at least outputs something to hard disk ;)
...hanu
Reinhard Nissl wrote:
> Hi,
>
> Petri Helin wrote:
>
>>> the attached vdr-1.5.9-h264.patch adds H.264 support to VDR's remuxer.
>>> The changes to earlier releases are:
>>>
>>> - H264::cParser has been enhanced to provide information for
>>> H264::cContext::GetFramesPerSec() and therefore outsourced
>>> into separate files.
>>> - cVideoRepacker generates Access Unit Delimiters in case they
>>> are not part of the stream.
>> Should this patch make it possible to record H.264 encoded stream? I
>
> It should. It works for the German DVB-S2 HD channels on Astra and it
> worked for LuxeTV HD on Hotbird in the past.
>
>> have applied the patch and can see in the channels menu that Canal+ HD
>> Film uses H.264 codec, but I can not record the channel (nor watch it...).
>
> Is this the channel you've mentioned (I've applied a DVB-S2 patch, so
> the entry may differ from your's a little)?
>
> CANAL+ FILM
> HD;Harmonic:11470:vC56M2S0Z0:S13.0E:27500:10331+331:332=pol;333=ORY:551:100:15423:318:1400:0
>
> On my system, VDR says this channel is encrypted. Do you have the
> necessary means to receive this channel?
>
The channel I mean is the same, I think, but provided by my local cable
operator. Here is the entry in channels.conf:
Canal+ Film
HD;Telenor:330000:C0M256:C:6900:10512+512:640=eng;641=eng:0:B00:3306:0:22:0
I have a valid subscription and this particular channel dis work when I
tested it with the ts-recording and h264-patches available here:
http://phivdr.dyndns.org/vdr
My subscription is ending in 24 hours, so I'd like to know if I can
record the channel before making my mind whether to continue the
subscription ;)
-Petri
Hi,
Petri Helin wrote:
> The channel I mean is the same, I think, but provided by my local cable
> operator. Here is the entry in channels.conf:
> Canal+ Film
> HD;Telenor:330000:C0M256:C:6900:10512+512:640=eng;641=eng:0:B00:3306:0:22:0
>
> I have a valid subscription and this particular channel dis work when I
> tested it with the ts-recording and h264-patches available here:
> http://phivdr.dyndns.org/vdr
Can you provide me with a few MB of TS stream from that channel?
Something like czap and cat /dev/dvb/adapterX/dvr0 > sample.ts should do
the trick.
> My subscription is ending in 24 hours, so I'd like to know if I can
> record the channel before making my mind whether to continue the
> subscription ;)
Then you have to hurry now, I won't have much time tomorrow evening.
Bye.
Hi,
Reinhard Nissl wrote:
> Can you provide me with a few MB of TS stream from that channel?
>
> Something like czap and cat /dev/dvb/adapterX/dvr0 > sample.ts should do
> the trick.
The TS sample you've sent me looks ok, i. e. it can be parsed by
H264::cParser.
Please locate the following location in cVideoRepacker::Repack() in file
remux.c:
// remember start of the data
const uchar *payload = data;
const uchar *NalPayload = payload;
while (todo > 0) {
and add the following line before the while:
if (h264parser) { static FILE *f = fopen("/video/sample.es.h264", "wb");
fwrite(data, 1, todo, f); fflush(f); }
The line will write the PES packet's content into file
/video/sample.es.h264 when a h264parser exists. Then please send me some
MB of the file.
Bye.
Hi,
Reinhard Nissl wrote:
> The line will write the PES packet's content into file
> /video/sample.es.h264 when a h264parser exists. Then please send me some
> MB of the file.
The file you've sent me doesn't contain any useful data. You can have a
look at it yourself:
od -Ax -t x1 -v sample2.es.h264 | less -S
You need to find at least the sequence 00 00 01. Otherwise it's garbage.
I'll go to bed soon, so here's a quick description how to go on:
- add this function to cRepacker
virtual void LogTS(const uint8_t *Buf) {}
- add this function to cVideoRepacker
virtual void LogTS(const uint8_t *Buf) { if (h264parser) { static FILE
*f = fopen("/video/sample.ts", "wb"); fwrite(Buf, 1, 188, f); fflush(f); } }
- change this area in ts_to_pes() like that:
void cTS2PES::ts_to_pes(const uint8_t *Buf) // don't need count (=188)
{
if (!Buf)
return;
if (repacker) repacker->LogTS(Buf);
if (Buf[1] & TS_ERROR)
Be careful to just have a single cVideoRepacker instance write into this
file, i. e. either activate transfer mode on this channel or make a
recording on this channel but not both at the same time.
Have a look at this file with
od -Ax -t x1 -v -w188 sample.ts | less -S
and locate the sequence 00 00 01 multiple times. It should then be
possible to record this channel although it doesn't work for now, as
cVideoRepacker didn't find any startcode (00 00 01) in the
sample.es.h264 from above.
Bye.
Reinhard Nissl wrote:
> Hi,
>
> Reinhard Nissl wrote:
>
>> The line will write the PES packet's content into file
>> /video/sample.es.h264 when a h264parser exists. Then please send me some
>> MB of the file.
>
> The file you've sent me doesn't contain any useful data. You can have a
> look at it yourself:
>
> od -Ax -t x1 -v sample2.es.h264 | less -S
>
> You need to find at least the sequence 00 00 01. Otherwise it's garbage.
>
> I'll go to bed soon, so here's a quick description how to go on:
>
> - add this function to cRepacker
> virtual void LogTS(const uint8_t *Buf) {}
> - add this function to cVideoRepacker
> virtual void LogTS(const uint8_t *Buf) { if (h264parser) { static FILE
> *f = fopen("/video/sample.ts", "wb"); fwrite(Buf, 1, 188, f); fflush(f); } }
> - change this area in ts_to_pes() like that:
>
> void cTS2PES::ts_to_pes(const uint8_t *Buf) // don't need count (=188)
> {
> if (!Buf)
> return;
> if (repacker) repacker->LogTS(Buf);
> if (Buf[1] & TS_ERROR)
>
> Be careful to just have a single cVideoRepacker instance write into this
> file, i. e. either activate transfer mode on this channel or make a
> recording on this channel but not both at the same time.
>
> Have a look at this file with
>
> od -Ax -t x1 -v -w188 sample.ts | less -S
>
> and locate the sequence 00 00 01 multiple times. It should then be
> possible to record this channel although it doesn't work for now, as
> cVideoRepacker didn't find any startcode (00 00 01) in the
> sample.es.h264 from above.
>
> Bye.
I have made the changes and did some testing, but there are no "00 00
01" series in the data at all. Some strange patterns I can see, but
mostly just garbage. I will try again this evening when I can be sure
that there is a program running.
Fortunately I remembered wrong the end date of my subscription, it is
valid until the end of this month, so I have 24 hours more to test this...
-Petri
> Reinhard Nissl wrote:
> the attached vdr-1.5.9-h264.patch adds H.264 support to VDR's remuxer.
Hi,
I trying to compile vdr-1.5.9 with h264 patches but vdr-xine-0.7.10 plugin give
me error:
xineDevice.c: In member function 'int PluginXine::cXineDevice::PlayCommon3(const
uchar*, int, int64_t)':
xineDevice.c:1387: error: cannot call member function 'int
cRemux::ScanVideoPacket(const uchar*, int, int, uchar&)' without object
xineDevice.c: In function 'bool PluginXine::getPTS(const uchar*, int, int64_t&,
bool, bool, double&, double&, double&, double&, double*)':
xineDevice.c:2017: error: cannot call member function 'int
cRemux::ScanVideoPacket(const uchar*, int, int, uchar&)' without object
make[1]: *** [xineDevice.o] Error 1
Is there any solution?
Please help me.
Regards,
AK
Reinhard Nissl wrote:
> Hi,
>
> Reinhard Nissl wrote:
>
>> The line will write the PES packet's content into file
>> /video/sample.es.h264 when a h264parser exists. Then please send me some
>> MB of the file.
>
> The file you've sent me doesn't contain any useful data. You can have a
> look at it yourself:
>
> od -Ax -t x1 -v sample2.es.h264 | less -S
>
> You need to find at least the sequence 00 00 01. Otherwise it's garbage.
>
> I'll go to bed soon, so here's a quick description how to go on:
>
> - add this function to cRepacker
> virtual void LogTS(const uint8_t *Buf) {}
> - add this function to cVideoRepacker
> virtual void LogTS(const uint8_t *Buf) { if (h264parser) { static FILE
> *f = fopen("/video/sample.ts", "wb"); fwrite(Buf, 1, 188, f); fflush(f); } }
> - change this area in ts_to_pes() like that:
>
> void cTS2PES::ts_to_pes(const uint8_t *Buf) // don't need count (=188)
> {
> if (!Buf)
> return;
> if (repacker) repacker->LogTS(Buf);
> if (Buf[1] & TS_ERROR)
>
> Be careful to just have a single cVideoRepacker instance write into this
> file, i. e. either activate transfer mode on this channel or make a
> recording on this channel but not both at the same time.
>
> Have a look at this file with
>
> od -Ax -t x1 -v -w188 sample.ts | less -S
>
> and locate the sequence 00 00 01 multiple times. It should then be
> possible to record this channel although it doesn't work for now, as
> cVideoRepacker didn't find any startcode (00 00 01) in the
> sample.es.h264 from above.
>
> Bye.
I have now tested when there is a program running (I am even seeing the
dvb-subtitles with xineliboutput), but still there are no "00 00 01"
series in the sample.ts. Anything more I could test with?
-Petri
On Thu, Aug 30, 2007 at 08:44:27PM +0300, Petri Helin wrote:
> I have now tested when there is a program running (I am even seeing the
> dvb-subtitles with xineliboutput), but still there are no "00 00 01"
> series in the sample.ts. Anything more I could test with?
I lost the stream also today. The subtitles were visible, but no sound.
vlc of course did not got anything to show.
After a several (10 - 15) try I did manage to tune to CD channel and got
sound also using xineliboutput. After getting the sound I did try vlc
and got stream also.
There is some problems on tuning or encrypting hd channels. Because I do
have only budget cards without cams, my canal+ card is on my dbox2 and
I'm using xx plugin to access the card.
...hanu
Hannu Tirkkonen wrote:
> There is some problems on tuning or encrypting hd channels.
Everything worked without problems when they used mpeg2 on Canal+ HD.
-Petri
Hi,
Petri Helin wrote:
> I have now tested when there is a program running (I am even seeing the
> dvb-subtitles with xineliboutput), but still there are no "00 00 01"
> series in the sample.ts. Anything more I could test with?
I'm sorry, I can't help you any further. Try to get a correctly
decrypted TS first, then it should work out of the box.
When you have a look at the first sample.ts you've sent me with this command
od -Ax -t x1 -v -w188 sample.ts | less -S
then you can find the sequence 00 00 01 09 which is a H.264 access unit
delimiter. So it once must have worked to get a properly decrypted TS.
Bye.
Reinhard Nissl wrote:
> Hi,
>
> Reinhard Nissl wrote:
>
> Have a look at this file with
>
> od -Ax -t x1 -v -w188 sample.ts | less -S
>
> and locate the sequence 00 00 01 multiple times. It should then be
> possible to record this channel although it doesn't work for now, as
> cVideoRepacker didn't find any startcode (00 00 01) in the
> sample.es.h264 from above.
>
> Bye.
I tried again by using streamdev-plugin to send TS-stream to a vlc
client, which I set to dump the TS-stream. In the dumped stream I can
find the "00 00 01" start codes.
-Petri
Reinhard Nissl wrote:
> Hi,
>
> Petri Helin wrote:
>
>> I have now tested when there is a program running (I am even seeing the
>> dvb-subtitles with xineliboutput), but still there are no "00 00 01"
>> series in the sample.ts. Anything more I could test with?
>
> I'm sorry, I can't help you any further. Try to get a correctly
> decrypted TS first, then it should work out of the box.
>
> When you have a look at the first sample.ts you've sent me with this command
>
> od -Ax -t x1 -v -w188 sample.ts | less -S
>
> then you can find the sequence 00 00 01 09 which is a H.264 access unit
> delimiter. So it once must have worked to get a properly decrypted TS.
>
> Bye.
When I tried again with streamdev-plugin sending TS-stream to a vlc
client and letting it dump the TS-stream, I can find the "00 00 01 09"
delimiter in the dumped stream. So if it works with the combination
above, what could be missing from VDR itself that prevents it from doing
the same?
-Petri
On Thu, Aug 30, 2007 at 12:05:08AM +0300, Hannu Tirkkonen wrote:
> I did apply this h264 patch and streamdev patch from:
> http://www.vdr-developer.org/mantisbt/view.php?id=382
>
> Now the load of the server is low when tuned to Canal+ HD and I can watch the stream using vlc.
> The recording at least outputs something to hard disk ;)
Well... the video part of the recordings seems to be corrupted.
vlc cannot show any video; there's only audio.
projectx says (hundreds of lines on 34MB recording):
!> error in pes_extension of pes-ID 0xBD @ pos: 112153 (1554 / 14 / 15 / true / false)
-> found PES-ID 0xBD (private stream 1) @ 112153
!> error in pes_extension of pes-ID 0xE0 @ pos: 134640 (2048 / 14 / 15 / true / false)
!> error in pes_extension of pes-ID 0xE0 @ pos: 188715 (2048 / 14 / 15 / true / false)
!> error in pes_extension of pes-ID 0xE0 @ pos: 247087 (2048 / 19 / 20 / true / false)
....
-> more than 500 warnings/errors, stop logging..
-> dropping video data, GOP larger than 6MB
-> dropping video data, GOP larger than 6MB
od does find 00 00 01 09 sequences from the file.
The live stream can be watched with vlc, and saving
the stream with vlc creates a file that can be watched again with mplayer or vlc.
There is 34MB of the recording on http://hotel.hanu.com/~hanu/h264
...hanu
On Fri, Aug 31, 2007 at 12:05:12AM +0300, Petri Helin wrote:
>
> When I tried again with streamdev-plugin sending TS-stream to a vlc
> client and letting it dump the TS-stream, I can find the "00 00 01 09"
> delimiter in the dumped stream. So if it works with the combination
> above, what could be missing from VDR itself that prevents it from doing
> the same?
Maybe there is something to do with the Welho's way of broadcasting
the Canal+ HD dvb-s2 stream again in dvb-c?
I do have a subscription also on Thor 1W, so I'll try to do some
tests using dvb-s2 during the weekend.
(The dish splitter is on another room, so there can be some
waf negotiations during the weekend ;))
..hanu
El Jueves, 30 de Agosto de 2007, Hannu Tirkkonen escribió:
> On Thu, Aug 30, 2007 at 12:05:08AM +0300, Hannu Tirkkonen wrote:
> > I did apply this h264 patch and streamdev patch from:
> > http://www.vdr-developer.org/mantisbt/view.php?id=382
> >
> > Now the load of the server is low when tuned to Canal+ HD and I can watch
> > the stream using vlc. The recording at least outputs something to hard
> > disk ;)
>
> Well... the video part of the recordings seems to be corrupted.
> vlc cannot show any video; there's only audio.
>
> projectx says (hundreds of lines on 34MB recording):
> !> error in pes_extension of pes-ID 0xBD @ pos: 112153 (1554 / 14 / 15 /
> true / false) -> found PES-ID 0xBD (private stream 1) @ 112153
> !> error in pes_extension of pes-ID 0xE0 @ pos: 134640 (2048 / 14 / 15 /
> true / false) !> error in pes_extension of pes-ID 0xE0 @ pos: 188715 (2048
> / 14 / 15 / true / false) !> error in pes_extension of pes-ID 0xE0 @ pos:
> 247087 (2048 / 19 / 20 / true / false) ....
I have this errors also with the ttxtsubs .They are not important in mpeg-2
streams. Perhaps ttxtsubs corupts the mpeg-4 stream.
Jose Alberto
> -> more than 500 warnings/errors, stop logging..
> -> dropping video data, GOP larger than 6MB
> -> dropping video data, GOP larger than 6MB
>
> od does find 00 00 01 09 sequences from the file.
>
> The live stream can be watched with vlc, and saving
> the stream with vlc creates a file that can be watched again with mplayer
> or vlc.
>
> There is 34MB of the recording on http://hotel.hanu.com/~hanu/h264
>
> ...hanu
>
> _______________________________________________
> vdr mailing list
> vdr@linuxtv.org
> http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr
Hi,
Arthur Konovalov wrote:
> I trying to compile vdr-1.5.9 with h264 patches but vdr-xine-0.7.10 plugin give
> me error:
>
> xineDevice.c: In member function 'int PluginXine::cXineDevice::PlayCommon3(const
> uchar*, int, int64_t)':
> xineDevice.c:1387: error: cannot call member function 'int
> cRemux::ScanVideoPacket(const uchar*, int, int, uchar&)' without object
> xineDevice.c: In function 'bool PluginXine::getPTS(const uchar*, int, int64_t&,
> bool, bool, double&, double&, double&, double&, double*)':
> xineDevice.c:2017: error: cannot call member function 'int
> cRemux::ScanVideoPacket(const uchar*, int, int, uchar&)' without object
> make[1]: *** [xineDevice.o] Error 1
>
> Is there any solution?
Use vdr-xine-0.7.11 please.
Bye.
Hi,
Hannu Tirkkonen wrote:
> Well... the video part of the recordings seems to be corrupted.
> vlc cannot show any video; there's only audio.
>
> projectx says (hundreds of lines on 34MB recording):
> !> error in pes_extension of pes-ID 0xBD @ pos: 112153 (1554 / 14 / 15 / true / false)
> -> found PES-ID 0xBD (private stream 1) @ 112153
> !> error in pes_extension of pes-ID 0xE0 @ pos: 134640 (2048 / 14 / 15 / true / false)
> !> error in pes_extension of pes-ID 0xE0 @ pos: 188715 (2048 / 14 / 15 / true / false)
> !> error in pes_extension of pes-ID 0xE0 @ pos: 247087 (2048 / 19 / 20 / true / false)
> ....
> -> more than 500 warnings/errors, stop logging..
> -> dropping video data, GOP larger than 6MB
> -> dropping video data, GOP larger than 6MB
ProjectX doesn't understand H.264. It assumes MPEG2 and therefore sees
an overfull GOP.
> od does find 00 00 01 09 sequences from the file.
>
> The live stream can be watched with vlc, and saving
> the stream with vlc creates a file that can be watched again with mplayer or vlc.
>
> There is 34MB of the recording on http://hotel.hanu.com/~hanu/h264
Plays perfectly here with vdr-xine-0.7.11 and xine-lib-cvs from my
homepage + vdr-xine's xine-lib.patch. If I play it in slow motion, my PC
is fast enough to decode and display all frames.
Bye.
Hi,
Hannu Tirkkonen wrote:
>> When I tried again with streamdev-plugin sending TS-stream to a vlc
>> client and letting it dump the TS-stream, I can find the "00 00 01 09"
>> delimiter in the dumped stream. So if it works with the combination
>> above, what could be missing from VDR itself that prevents it from doing
>> the same?
>
> Maybe there is something to do with the Welho's way of broadcasting
> the Canal+ HD dvb-s2 stream again in dvb-c?
>
> I do have a subscription also on Thor 1W, so I'll try to do some
> tests using dvb-s2 during the weekend.
Please keep in mind, that my patch doesn't add DVB-S2 support.
Bye.
On 8/29/07, Reinhard Nissl <rnissl@gmx.de> wrote:
> Hi,
>
> the attached vdr-1.5.9-h264.patch adds H.264 support to VDR's remuxer.
>
> These changes should make VDR ready for the upcoming IFA fair in regard
> to the broadcasts on the temporary channel EinsFestival HD.
>
Referring to the problems I've had with this patch, I'd like to know
if the reason was that the channel I'm trying to watch/record is
encrypted. Have you had chance to test this with an encrypted channel?
Or is that out of the question and the reason is something else?
-Petri
Hi,
Petri Helin wrote:
>> the attached vdr-1.5.9-h264.patch adds H.264 support to VDR's remuxer.
>>
>> These changes should make VDR ready for the upcoming IFA fair in regard
>> to the broadcasts on the temporary channel EinsFestival HD.
>
> Referring to the problems I've had with this patch, I'd like to know
> if the reason was that the channel I'm trying to watch/record is
> encrypted. Have you had chance to test this with an encrypted channel?
No, I didn't have a chance to test this.
> Or is that out of the question and the reason is something else?
One part of my patch adds some functionality to cVideoRepacker and
therefore has no influence on the TS level.
But another part modifies VPID to transport the information that this
channel uses H.264. This is done by adding 10000 to the normal VPID
which is in the range 0..8191. The decimal offset 10000 was chosen over
the hex offset 0x10000 as the real VPID should still be recognizable in
channels.conf without using a calculator.
The drawback is, that the decimal offset isn't simply clipped away by
assigning the patched VPID for example to a variable of type short or
when masking it with 0x1fff. Therefore it is necessary to add some
special clipping code at each location where the patched VPID is entered
into some data structure which is then given to DVB API functions.
So, there is the chance that this clipping is missing at a location
where the VPID is scheduled for decrypting. This could be the reason why
the video TS packets do not get decrypted.
But I don't understand why streamdev still delivers a decrypted video
stream in that case. Can it be that the client asks streamdev to filter
certain TS packets and therefore uses the correct VPID?
Bye.
Reinhard Nissl wrote:
> But I don't understand why streamdev still delivers a decrypted video
> stream in that case. Can it be that the client asks streamdev to filter
> certain TS packets and therefore uses the correct VPID?
Yes. In http streaming mode streamdev parses PIDs directly from PMT and
does not use VDR channel data. But the VDR<->VDR streaming mode probably
does not work if PIDs are not "real" ones.
- Petri
@@ -182,8 +182,8 @@ bool cNonBlockingFileReader::WaitForData
#define PLAYERBUFSIZE MEGABYTE(1)
-// The number of frames to back up when resuming an interrupted replay session:
-#define RESUMEBACKUP (10 * FRAMESPERSEC)
+// The number of seconds to back up when resuming an interrupted replay session:
+#define RESUMEBACKUP 10
class cDvbPlayer : public cPlayer, cThread {
private:
@@ -196,6 +196,7 @@ private:
cFileName *fileName;
cIndexFile *index;
cUnbufferedFile *replayFile;
+ int framesPerSec;
bool eof;
bool firstPacket;
ePlayModes playMode;
@@ -225,6 +226,7 @@ public:
void Goto(int Position, bool Still = false);
virtual bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false);
virtual bool GetReplayMode(bool &Play, bool &Forward, int &Speed);
+ int GetFramesPerSec(void) { return framesPerSec; }
};
#define MAX_VIDEO_SLOWMOTION 63 // max. arg to pass to VIDEO_SLOWMOTION // TODO is this value correct?
@@ -253,6 +255,7 @@ cDvbPlayer::cDvbPlayer(const char *FileN
replayFile = fileName->Open();
if (!replayFile)
return;
+ framesPerSec = replayFile->GetFramesPerSec();
ringBuffer = new cRingBufferFrame(PLAYERBUFSIZE);
// Create the index file:
index = new cIndexFile(FileName, false);
@@ -341,7 +344,7 @@ bool cDvbPlayer::Save(void)
if (index) {
int Index = writeIndex;
if (Index >= 0) {
- Index -= RESUMEBACKUP;
+ Index -= RESUMEBACKUP * GetFramesPerSec();
if (Index > 0)
Index = index->GetNextIFrame(Index, false);
else
@@ -371,7 +374,7 @@ void cDvbPlayer::Action(void)
readIndex = Resume();
if (readIndex >= 0)
- isyslog("resuming replay at index %d (%s)", readIndex, *IndexToHMSF(readIndex, true));
+ isyslog("resuming replay at index %d (%s)", readIndex, *IndexToHMSF(readIndex, true, GetFramesPerSec()));
nonBlockingFileReader = new cNonBlockingFileReader;
int Length = 0;
@@ -667,7 +670,7 @@ void cDvbPlayer::SkipSeconds(int Seconds
Empty();
int Index = writeIndex;
if (Index >= 0) {
- Index = max(Index + Seconds * FRAMESPERSEC, 0);
+ Index = max(Index + Seconds * GetFramesPerSec(), 0);
if (Index > 0)
Index = index->GetNextIFrame(Index, false, NULL, NULL, NULL, true);
if (Index >= 0)
@@ -834,3 +838,10 @@ void cDvbPlayerControl::Goto(int Positio
if (player)
player->Goto(Position, Still);
}
+
+int cDvbPlayerControl::GetFramesPerSec()
+{
+ if (player)
+ return player->GetFramesPerSec();
+ return FRAMESPERSEC;
+}
@@ -54,6 +54,8 @@ public:
void Goto(int Index, bool Still = false);
// Positions to the given index and displays that frame as a still picture
// if Still is true.
+ int GetFramesPerSec();
+ // Returns the number of frames per second for the current recording.
};
#endif //__DVBPLAYER_H
@@ -4014,7 +4026,7 @@ bool cReplayControl::ShowProgress(bool I
lastCurrent = lastTotal = -1;
}
if (Total != lastTotal) {
- displayReplay->SetTotal(IndexToHMSF(Total));
+ displayReplay->SetTotal(IndexToHMSF(Total, false, GetFramesPerSec()));
if (!Initial)
displayReplay->Flush();
}
@@ -4022,7 +4034,7 @@ bool cReplayControl::ShowProgress(bool I
displayReplay->SetProgress(Current, Total);
if (!Initial)
displayReplay->Flush();
- displayReplay->SetCurrent(IndexToHMSF(Current, displayFrames));
+ displayReplay->SetCurrent(IndexToHMSF(Current, displayFrames, GetFramesPerSec()));
displayReplay->Flush();
lastCurrent = Current;
}
@@ -4055,8 +4067,8 @@ void cReplayControl::TimeSearchProcess(e
{
#define STAY_SECONDS_OFF_END 10
int Seconds = (timeSearchTime >> 24) * 36000 + ((timeSearchTime & 0x00FF0000) >> 16) * 3600 + ((timeSearchTime & 0x0000FF00) >> 8) * 600 + (timeSearchTime & 0x000000FF) * 60;
- int Current = (lastCurrent / FRAMESPERSEC);
- int Total = (lastTotal / FRAMESPERSEC);
+ int Current = (lastCurrent / GetFramesPerSec());
+ int Total = (lastTotal / GetFramesPerSec());
switch (Key) {
case k0 ... k9:
if (timeSearchPos < 4) {
@@ -4083,7 +4095,7 @@ void cReplayControl::TimeSearchProcess(e
case kDown:
case kOk:
Seconds = min(Total - STAY_SECONDS_OFF_END, Seconds);
- Goto(Seconds * FRAMESPERSEC, Key == kDown || Key == kPause || Key == kOk);
+ Goto(Seconds * GetFramesPerSec(), Key == kDown || Key == kPause || Key == kOk);
timeSearchActive = false;
break;
default:
@@ -4204,7 +4216,7 @@ void cReplayControl::EditTest(void)
if ((m->Index() & 0x01) != 0)
m = marks.Next(m);
if (m) {
- Goto(m->position - SecondsToFrames(3));
+ Goto(m->position - SecondsToFrames(3, GetFramesPerSec()));
Play();
}
}
@@ -1481,11 +1481,11 @@ cUnbufferedFile *cFileName::NextFile(voi
// --- Index stuff -----------------------------------------------------------
-cString IndexToHMSF(int Index, bool WithFrame)
+cString IndexToHMSF(int Index, bool WithFrame, int FramesPerSec)
{
char buffer[16];
- int f = (Index % FRAMESPERSEC) + 1;
- int s = (Index / FRAMESPERSEC);
+ int f = (Index % FramesPerSec) + 1;
+ int s = (Index / FramesPerSec);
int m = s / 60 % 60;
int h = s / 3600;
s %= 60;
@@ -1493,17 +1493,17 @@ cString IndexToHMSF(int Index, bool With
return buffer;
}
-int HMSFToIndex(const char *HMSF)
+int HMSFToIndex(const char *HMSF, int FramesPerSec)
{
int h, m, s, f = 0;
if (3 <= sscanf(HMSF, "%d:%d:%d.%d", &h, &m, &s, &f))
- return (h * 3600 + m * 60 + s) * FRAMESPERSEC + f - 1;
+ return (h * 3600 + m * 60 + s) * FramesPerSec + f - 1;
return 0;
}
-int SecondsToFrames(int Seconds)
+int SecondsToFrames(int Seconds, int FramesPerSec)
{
- return Seconds * FRAMESPERSEC;
+ return Seconds * FramesPerSec;
}
// --- ReadFrame -------------------------------------------------------------
@@ -233,11 +233,11 @@ public:
cUnbufferedFile *NextFile(void);
};
-cString IndexToHMSF(int Index, bool WithFrame = false);
+cString IndexToHMSF(int Index, bool WithFrame = false, int FramesPerSec = FRAMESPERSEC);
// Converts the given index to a string, optionally containing the frame number.
-int HMSFToIndex(const char *HMSF);
+int HMSFToIndex(const char *HMSF, int FramesPerSec = FRAMESPERSEC);
// Converts the given string (format: "hh:mm:ss.ff") to an index.
-int SecondsToFrames(int Seconds); //XXX+ ->player???
+int SecondsToFrames(int Seconds, int FramesPerSec = FRAMESPERSEC); //XXX+ ->player???
// Returns the number of frames corresponding to the given number of seconds.
int ReadFrame(cUnbufferedFile *f, uchar *b, int Length, int Max);
@@ -1297,8 +1297,10 @@ void cSVDRP::CmdPLAY(const char *Option)
int x = sscanf(option, "%d:%d:%d.%d", &h, &m, &s, &f);
if (x == 1)
pos = h;
- else if (x >= 3)
- pos = (h * 3600 + m * 60 + s) * FRAMESPERSEC + f - 1;
+ else if (x >= 3) {
+ int FramesPerSec = cUnbufferedFile::GetFramesPerSec(recording->FileName());
+ pos = (h * 3600 + m * 60 + s) * FramesPerSec + f - 1;
+ }
}
cResumeFile resume(recording->FileName());
if (pos <= 0)
@@ -27,6 +27,8 @@ extern "C" {
#include <utime.h>
#include "i18n.h"
#include "thread.h"
+#include "remux.h"
+#include "recording.h"
int SysLogLevel = 3;
@@ -1566,6 +1568,112 @@ cUnbufferedFile *cUnbufferedFile::Create
return File;
}
+int cUnbufferedFile::GetFramesPerSec(const char *FileName)
+{
+ // use this constant as a fallback value
+ int FramesPerSec = FRAMESPERSEC;
+ // open the file an determine frames per second
+ cFileName fn(FileName, false);
+ cUnbufferedFile *f = fn.Open();
+ if (f) {
+ FramesPerSec = f->GetFramesPerSec();
+ fn.Close();
+ }
+ return FramesPerSec;
+}
+
+#define ADD_H264_SUPPORT 1
+
+#ifdef ADD_H264_SUPPORT
+#include "h264parser.h"
+#endif
+
+int cUnbufferedFile::GetFramesPerSec(void)
+{
+ // use this constant as a fallback value
+ int FramesPerSec = FRAMESPERSEC;
+ // rember current file position to restore later
+ off_t OrigPos = curpos;
+ // seek to the beginning and read a chunk of data
+ if (0 == Seek(0, SEEK_SET)) {
+ uchar Data[2048];
+ ssize_t Count = Read(Data, sizeof(Data));
+ if (Count > 0) {
+ // this chunk of data should actually be a PES packet
+ uchar *Limit = Data + Count;
+ int PesPayloadOffset = 0;
+ if (AnalyzePesHeader(Data, Count, PesPayloadOffset) == phMPEG2) {
+ // we need a video stream -- radio recordings use the default
+ if ((Data[3] & 0xF0) == 0xE0) {
+ uchar *p = Data + PesPayloadOffset;
+#ifdef ADD_H264_SUPPORT
+ // check whether this is a H.264 video frame
+ if (cRemux::IsFrameH264(Data, Count)) {
+ // need to have a H264 parser since picture timing is rather complex
+ H264::cParser H264parser(false);
+ // send NAL units to parser until it is able to provide frames per second
+ while (p < Limit) {
+ // find next NAL unit
+ uchar *pNext = (uchar *)memmem(p + 4, Limit - (p + 4), "\x00\x00\x01", 3);
+ if (!pNext) // just pass the remainder
+ pNext = Limit;
+ H264parser.PutNalUnitData(p, pNext - p);
+ // process NAL unit and check for frames per second
+ H264parser.Process();
+ int FPS = H264parser.Context().GetFramesPerSec();
+ if (FPS != -1) { // there we are ;-)
+ FramesPerSec = FPS;
+fprintf(stderr, "FramesPerSec: %d\n", FramesPerSec);
+ break;
+ }
+ // continue with next NAL unit
+ p = pNext;
+ }
+ }
+ else {
+#endif
+ // thanks to cVideoRepacker, the payload starts with a sequence header
+ if (p + 12 <= Limit) {
+ if (p[0] == 0x00 && p[1] == 0x00 && p[2] == 0x01 && p[3] == 0xB3) {
+ uint32_t frame_rate_code = p[7] & 0x0F;
+ uint32_t frame_rate_extension_n = 0;
+ uint32_t frame_rate_extension_d = 0;
+ // now we need to have a look at the next startcode,
+ // as it might be a sequence extension
+ p = (uchar *)memmem(p + 12, Limit - (p + 12), "\x00\x00\x01", 3);
+ if (p && p + 4 < Limit && p[3] == 0xB5) { // extension start code
+ if (p + 5 < Limit && (p[4] >> 4) == 0x1) { // sequence extension
+ if (p + 10 < Limit) {
+ frame_rate_extension_n = (p[9] & 0x60) >> 5;
+ frame_rate_extension_d = (p[9] & 0x1F);
+ }
+ }
+ }
+ // calculate frame rate and round it for compatibility
+ if (0x1 <= frame_rate_code && frame_rate_code <= 0x8) {
+ static const int n[] = { -1, 24000, 24, 25, 30000, 30, 50, 60000, 60 };
+ static const int d[] = { -1, 1001, 1, 1, 1001, 1, 1, 1001, 1 };
+ double frame_rate = n[frame_rate_code] * (frame_rate_extension_n + 1)
+ / (double)(d[frame_rate_code] * (frame_rate_extension_d + 1));
+ FramesPerSec = (int)frame_rate;
+ if (frame_rate - FramesPerSec > 0.5)
+ FramesPerSec++;
+fprintf(stderr, "FramesPerSec: %d\n", FramesPerSec);
+ }
+ }
+ }
+#ifdef ADD_H264_SUPPORT
+ }
+#endif
+ }
+ }
+ }
+ }
+ // restore original position
+ Seek(OrigPos, SEEK_SET);
+ return FramesPerSec;
+}
+
// --- cLockFile -------------------------------------------------------------
#define LOCKFILENAME ".lock-vdr"
@@ -349,6 +349,8 @@ public:
ssize_t Read(void *Data, size_t Size);
ssize_t Write(const void *Data, size_t Size);
static cUnbufferedFile *Create(const char *FileName, int Flags, mode_t Mode = DEFFILEMODE);
+ static int GetFramesPerSec(const char *FileName);
+ int GetFramesPerSec(void);
};
class cLockFile {