[ANNOUNCE] DVB-S2 + H.264 support for VDR-1.5.10

Message ID 47165196.8040209@gmx.de
State New
Headers

Commit Message

Reinhard Nissl Oct. 17, 2007, 6:16 p.m. UTC
  Hi,

attached you'll find an updated patch for VDR-1.5.10. It replaces the
formerly patch for VDR-1.5.9.

Have a look at this page for more instructions on this concern:

http://www.vdr-wiki.de/wiki/index.php/OpenSuSE_DVB-S2_-_Step_by_Step_Installationsanleitung_%28Achtung_Beta%29

Bye.
  

Comments

Georg Acher Oct. 17, 2007, 6:48 p.m. UTC | #1
On Wed, Oct 17, 2007 at 08:16:54PM +0200, Reinhard Nissl wrote:
> Hi,
> 
> attached you'll find an updated patch for VDR-1.5.10. It replaces the
> formerly patch for VDR-1.5.9.

I still don't understand why you want to record h.264 in PES...
  
Jan Wagner Oct. 18, 2007, 4:44 a.m. UTC | #2
Hi there,

> attached you'll find an updated patch for VDR-1.5.10. It replaces the
> formerly patch for VDR-1.5.9.

could you seperate the patch into H.264 and DVB-S2 parts again? I use
DVB-C with it here and do not want to upgrade to drivers with DVB-S2
support.

> Have a look at this page for more instructions on this concern:
> 
> http://www.vdr-wiki.de/wiki/index.php/OpenSuSE_DVB-S2_-_Step_by_Step_Installationsanleitung_%28Achtung_Beta%29

These are really nice and work fine.

Cheers and many thanks for your efforts!

Jan
  
Joerg Knitter Oct. 19, 2007, 8:24 a.m. UTC | #3
Georg Acher schrieb:
> On Wed, Oct 17, 2007 at 08:16:54PM +0200, Reinhard Nissl wrote:
>> Hi,
>>
>> attached you'll find an updated patch for VDR-1.5.10. It replaces the
>> formerly patch for VDR-1.5.9.
> 
> I still don't understand why you want to record h.264 in PES...

Furthermore: How do I demux a h.264 PES recording? With TS files 
recorded on Windows I used the tool "xport" which also takes care of 
proper audio sync. ProjectX still does not support H.264.

Nevertheless: Thanks a lot, hope that I get it working within the next 
days, especially for checking if my system is fast enough for 
software-only decoding.

With kind regards

Joerg Knitter
  
Goga777 Oct. 21, 2007, 10:36 a.m. UTC | #4
Hello Reinhard

it's interesting - is there some opinion from VDR's users about this path ? Which h.264 dvb-s2 channels is
it possible to watch really ? What about CPU's load during this ? which hardware (dvb-s2 card, cpu,
graphic card) use ?

regards
Igor
  
Morfsta Oct. 22, 2007, 11:55 a.m. UTC | #5
Hi,

I tried the patch yesterday on my desktop computer: -

2.13Ghz Intel Core 2 CPU
2Gb RAM
Nvidia 6200LE PCI-E graphics card
400Gb IDE (not SATA) hard disk
Skystar 2 DVB-S
Latest Ubuntu with xorg
Latest NVIDIA Drivers
Hooked up DVI -> HDMI on a Pioneer 43" plasma TV at 720p (native
resolution of the panel = 1024x768) and using 32bpp on the desktop.
vdr-1.5.9 with the earlier h264 patch (I didn't see the seperated
patch for 1.5.10 yesterday)
xine-lib-cvs

The only test channel I could try it on at the moment is the BBC HD
service on Astra 2 which is FTA, DVB-S and mpeg4 (MBAFF).  Used tvtime
Greedy2Frame deinterlacer in xine.

The picture was very good, but there was dropped frames that xine
reported and the stuttered on occassion and then ran very quickly to
catch up. Playing around with the settings in xine (setting threads to
2 etc) didn't really make much difference. However, for the first time
I've spent playing with this I was impressed with the picture quality
out of VDR. Top reported that the CPU was ~40% idle so I don't know
why I saw dropped frames...

One other thing I noticed though was when using XVMC (-V xxmc) to view
normal MPEG2 channels the VDR OSD looked terrible (very blockly
looking) and playing with the settings in the xine plugin did not make
it better. Any recommendations on improving this? When using MPEG4
(i.e. software accel)  the OSD was fine.

Any thoughts on this anyone and/or Reinhard?

Cheers

Morfsta




On 10/21/07, Igor Nikanov <goga777@bk.ru> wrote:
> Hello Reinhard
>
> it's interesting - is there some opinion from VDR's users about this path ? Which h.264 dvb-s2 channels is
> it possible to watch really ? What about CPU's load during this ? which hardware (dvb-s2 card, cpu,
> graphic card) use ?
>
> regards
> Igor
>
>
> _______________________________________________
> vdr mailing list
> vdr@linuxtv.org
> http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr
>
  
Goga777 Oct. 22, 2007, 6:53 p.m. UTC | #6
Hello, Morfsta


thanks you very much for your report

> vdr-1.5.9 with the earlier h264 patch (I didn't see the seperated
> patch for 1.5.10 yesterday)

can you try with yesterday patch for 1.5.10 ?


> The only test channel I could try it on at the moment is the BBC HD
> service on Astra 2 which is FTA, DVB-S and mpeg4 (MBAFF).  Used tvtime
> Greedy2Frame deinterlacer in xine.

can you try with others dvb-s FTA hdtv channels ?
http://ru.kingofsat.net/hdtv.php

regards
Igor
  
Reinhard Nissl Oct. 24, 2007, 7:04 a.m. UTC | #7
Hi,

Morfsta schrieb:

> The picture was very good, but there was dropped frames that xine
> reported and the stuttered on occassion and then ran very quickly to
> catch up. Playing around with the settings in xine (setting threads to
> 2 etc) didn't really make much difference. However, for the first time
> I've spent playing with this I was impressed with the picture quality
> out of VDR. Top reported that the CPU was ~40% idle so I don't know
> why I saw dropped frames...

Frame duration wasn't set at all in xine-lib for this case. xine-lib-1.2
contains now a fix for this issue. The fix is part of vdr-xine-0.8.0's
xine-lib.patch for xine-lib-1.1.8, too.

> One other thing I noticed though was when using XVMC (-V xxmc) to view
> normal MPEG2 channels the VDR OSD looked terrible (very blockly
> looking) and playing with the settings in the xine plugin did not make
> it better. Any recommendations on improving this? When using MPEG4
> (i.e. software accel)  the OSD was fine.

xxmc's OSD support allows only 16 colors. I assume, you've enabled font
antialiasing in VDR, which requires much more than 16 colors. This is
the case for hardware accelerated MPEG2 decoding. For H.264, xxmc falls
back to xv where there is no such limitation.

You may also want to try to choose unscaled OSD in vdr-xine's setup
menu, which renders the OSD on top of the video image, using libX11. It
is therefore not limited to 16 colors but doesn't support OSD
transparency at all.

Bye.
  
Tony Grant Oct. 24, 2007, 7:29 a.m. UTC | #8
Le mercredi 24 octobre 2007 à 09:04 +0200, Reinhard Nissl a écrit :

> > The picture was very good, but there was dropped frames that xine
> > reported and the stuttered on occassion and then ran very quickly to
> > catch up. Playing around with the settings in xine (setting threads to
> > 2 etc) didn't really make much difference. However, for the first time
> > I've spent playing with this I was impressed with the picture quality
> > out of VDR. Top reported that the CPU was ~40% idle so I don't know
> > why I saw dropped frames...
> 
> Frame duration wasn't set at all in xine-lib for this case. xine-lib-1.2
> contains now a fix for this issue. The fix is part of vdr-xine-0.8.0's
> xine-lib.patch for xine-lib-1.1.8, too.

Reinhard,

Where can I find xine-lib-1.2?

Without patching and using the 0.3.0 CPU is back down under 40% on my
Epia M10000

Cheers

Tony


--
  
Reinhard Nissl Oct. 24, 2007, 7:47 a.m. UTC | #9
Hi,

Tony Grant schrieb:

>> Frame duration wasn't set at all in xine-lib for this case. xine-lib-1.2
>> contains now a fix for this issue. The fix is part of vdr-xine-0.8.0's
>> xine-lib.patch for xine-lib-1.1.8, too.
> 
> Where can I find xine-lib-1.2?

xine-lib-1.2 is only available from the hg repository. Please follow
this guide:

http://www.vdr-wiki.de/wiki/index.php/OpenSuSE_DVB-S2_-_Step_by_Step_Installationsanleitung_%28Achtung_Beta%29

Although not required, I'd suggest you to use vdr-xine-0.8.0 too (see
other thread about fixes).

Bye.
  
Tony Grant Oct. 24, 2007, 2:44 p.m. UTC | #10
Le mercredi 24 octobre 2007 à 09:47 +0200, Reinhard Nissl a écrit :

> xine-lib-1.2 is only available from the hg repository. Please follow
> this guide:

OK I have lib-1.2 and vdr-xine-0.8.0 humming along. Image very clean and
CPU usage is down another 5%. I will see if the new version of
openchrome and libXVmc fixes something (CPU was 15% when I started this
VDR journey). Zaps fast. Locks solid when right clicking to get the xine
menu...

How do I set the PCM volume on startup? The setting in the OSD?

Cheers

Tony

--
  
Torgeir Veimo Oct. 24, 2007, 3 p.m. UTC | #11
On 24 Oct 2007, at 15:44, Tony Grant wrote:

>
> OK I have lib-1.2 and vdr-xine-0.8.0 humming along. Image very  
> clean and
> CPU usage is down another 5%. I will see if the new version of
> openchrome and libXVmc fixes something (CPU was 15% when I started  
> this
> VDR journey). Zaps fast. Locks solid when right clicking to get the  
> xine
> menu...

Is there any support for h.264 decoding in any of the linux support  
libraries for the CN700 now?

Otherwise I'd assume that XvMC was not in use when not doing mpeg2  
decoding.
  
Reinhard Nissl Oct. 24, 2007, 4:19 p.m. UTC | #12
Hi,

Tony Grant schrieb:

> OK I have lib-1.2 and vdr-xine-0.8.0 humming along. Image very clean and
> CPU usage is down another 5%. I will see if the new version of
> openchrome and libXVmc fixes something (CPU was 15% when I started this
> VDR journey). Zaps fast. Locks solid when right clicking to get the xine
> menu...

It would be interesting, where the deadlock occurs. To analyze the
deadlock, please compile xine-lib and xine-ui with debug information by
running configure like that:

CFLAGS='-g3 -O0' ../xine-lib/configure --prefix=/soft/xine-lib-cvs
--enable-debug --disable-optimizations --with-external-ffmpeg --disable-dxr3

CFLAGS='-g3 -O0' ../xine-ui/configure --prefix=/soft/xine-ui-cvs
--enable-debug --disable-optimizations --enable-vdr-keys

When the deadlock occurs, run gdb like that:

	gdb /path/to/xine `pidof xine`

There will be a lot of libraries listed by gdb. Among the output gdb
will also report for which libraries it could find debug symbols. For
the best result, try to install missing debug symbols if your Linux
distribution provides them. For simplicity, quit gdb by typing quit and
let xine alive. Restart gdb as mentioned above until debug symbols for
all libraries are available.

Then type the following command into gdb:

	thread apply all bt

gdb will then output the backtrace of each thread (and there will be
about 20). Please report the backtraces here.

> How do I set the PCM volume on startup? The setting in the OSD?

When VDR sets the volume, vdr-xine stores this value internally. When
xine connects to vdr-xine, the stored value will be transmitted to xine.

Please have a look into VDR's setup menu. There exists a setting which
controls whether VDR shall restore the last set volume when it starts.
When VDR doesn't restore the volume setting, then vdr-xine's internal
value will be 0 and xine's volume will be set to 0, too.

Bye.
  
Morfsta Oct. 25, 2007, 11:22 a.m. UTC | #13
Hi Reinhard,

I have downloaded and installed the latest CVS of ffmpeg and xine-lib
as well as installing the latest vdr-xine-0.8.0. I again followed the
general compilation instructions at the Open Suse DVB-S2 instructions
page.

I have just tried it on BBC HD (Astra 2 - H264/MBAFF) as well as HD2/5
(Astra 3 H264/???) and I get video jumping every 2 seconds. Here is
the [clipped] output from xine (verbose=3): -

video_out_xshm: video mode depth is 24 (32 bpp), TrueColor, not swapped,
video_out_xshm: red: 00ff0000, green: 0000ff00, blue: 000000ff
x11osd: unscaled overlay created (XShape mode).
video_out: thread created
audio_alsa_out : supported modes are 8bit 16bit 24bit mono stereo
(4-channel not enabled in xine config) (4.1-channel not enabled in
xine config) (5-channel not enabled in xine config) (5.1-channel not
enabled in xine config) (a/52 and DTS pass-through not enabled in xine
config)
audio_out: thread created
xine_stream_new
video_out: thread created
audio_out: thread created
xine_interface: unknown or deprecated stream param 10 set
xine_stream_new
xine_interface: unknown or deprecated stream param 10 set
xine_stream_new
xine_interface: unknown or deprecated stream param 10 set
video_out_xshm: aspect ratio changed to 16:9
video_out_xshm: tried to get unsupported property 2
video_out_xshm: tried to set unsupported property 2
video_out_xshm: tried to get unsupported property 2
gui_xine_open_and_play():
	mrl: 'vdr://tmp/vdr-xine/stream#demux:mpeg_pes',
	sub 'NONE',
	start_pos 0, start_time 0, av_offset 0, spu_offset 0.
xine: found input plugin  : VDR display device plugin
xine: found demuxer plugin: mpeg pes demux plugin
video discontinuity #1, type is 0, disc_off 0
waiting for audio discontinuity #1
audio discontinuity #1, type is 0, disc_off 0
waiting for in_discontinuity update #1
vpts adjusted with prebuffer to 38099
av_offset=0 pts
spu_offset=0 pts
xine_play
play_internal ...done
ratio: 0
prebuffer=0 pts
+++ CLEAR(-1a)
ao_flush (loop running: 1)
=== CLEAR(-1.1)
video discontinuity #2, type is 0, disc_off 0
waiting for audio discontinuity #2
audio discontinuity #2, type is 0, disc_off 0
waiting for in_discontinuity update #2
vpts adjusted with prebuffer to 26139
=== CLEAR(-1.2)
=== CLEAR(-1.3)
=== CLEAR(-1.4)
=== CLEAR(-1.5)
--- CLEAR(-1a)
+++ CLEAR(-1b)
ao_flush (loop running: 1)
=== CLEAR(-1.1)
video discontinuity #3, type is 0, disc_off 0
waiting for audio discontinuity #3
audio discontinuity #3, type is 0, disc_off 0
waiting for in_discontinuity update #3
vpts adjusted with prebuffer to 26166
=== CLEAR(-1.2)
=== CLEAR(-1.3)
=== CLEAR(-1.4)
=== CLEAR(-1.5)
--- CLEAR(-1b)
video_out_xshm: tried to set unsupported property 0
load_plugins: plugin mpeg2 will be used for video streamtype 00.
video_out_xshm: tried to set unsupported property 0
vdr_video: osd: (0, 0)-(720, 576)@1.33333
video_out_xshm: tried to get unsupported property 8
video_out_xshm: tried to get unsupported property 13
ratio: 13333
video_out_xshm: tried to set unsupported property 8
video_out_xshm: tried to set unsupported property 13
vdr: flush: n: 77, 941.1
input_vdr: flush buffers (vb: 0, ab: 0, vf: 0, af: 0) done.
+++ CLEAR(-5a)
ao_flush (loop running: 1)
=== CLEAR(-5.1)
=== CLEAR(-5.2)
=== CLEAR(-5.3)
=== CLEAR(-5.4)
=== CLEAR(-5.5)
--- CLEAR(-5a)
video_out_xshm: tried to set unsupported property 0
video discontinuity #4, type is 0, disc_off 0
waiting for audio discontinuity #4
audio discontinuity #4, type is 0, disc_off 0
waiting for in_discontinuity update #4
vpts adjusted with prebuffer to 113685
ao_flush (loop running: 1)
=== CLEAR(-5.1)
=== CLEAR(-5.2)
=== CLEAR(-5.3)
=== CLEAR(-5.4)
=== CLEAR(-5.5)
--- CLEAR(-5b)
video discontinuity #5, type is 0, disc_off 0
waiting for audio discontinuity #5
audio discontinuity #5, type is 0, disc_off 0
waiting for in_discontinuity update #5
vpts adjusted with prebuffer to 113716
set_speed 125000
video_out_xshm: tried to set unsupported property 0
load_plugins: plugin mpeg2 will be used for video streamtype 00.
video discontinuity #6, type is 2, disc_off 7837506763
waiting for audio discontinuity #6
load_plugins: plugin mad will be used for audio streamtype 01.
upmix_mono: upmixing a single channel from original 2 channels stream.
audio_alsa_out:open pause_resume=0
output sample rate 48000
audio discontinuity #6, type is 2, disc_off 7837506763
waiting for in_discontinuity update #6
video vpts adjusted to audio vpts 115876
audio jump, diff=0
video_out_xshm: tried to set unsupported property 0
video discontinuity #7, type is 0, disc_off 0
waiting for audio discontinuity #7
ao_close
audio_out: no streams left, closing driver
audio discontinuity #7, type is 0, disc_off 0
waiting for in_discontinuity update #7
vpts adjusted with prebuffer to 118377
video discontinuity #8, type is 2, disc_off 7837566420
waiting for audio discontinuity #8
audio discontinuity #8, type is 2, disc_off 7837566420
waiting for in_discontinuity update #8
vpts adjusted with prebuffer to 118378
load_plugins: plugin ffmpegvideo will be used for video streamtype 4d.
load_plugins: plugin mad will be used for audio streamtype 01.
upmix_mono: upmixing a single channel from original 2 channels stream.
video_out_xshm: tried to set unsupported property 0
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]no frame!
ffmpeg_video_dec: error decompressing frame
vdr_video: osd: (0, 0)-(1, 1)@1
video_out_xshm: tried to get unsupported property 8
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
ratio: 10000
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]no frame!
ffmpeg_video_dec: error decompressing frame
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]no frame!
ffmpeg_video_dec: error decompressing frame
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]no frame!
ffmpeg_video_dec: error decompressing frame
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]non existing PPS referenced
[h264 @ 0x2aaaace75800]decode_slice_header error
[h264 @ 0x2aaaace75800]no frame!
ffmpeg_video_dec: error decompressing frame
audio_alsa_out:open pause_resume=0
output sample rate 48000
audio jump, diff=51017
ffmpeg_video_dec: increasing buffer to 198787 to avoid overflow.
vdr_video: osd: (0, 0)-(1440, 1080)@1.77778
video jump
video_out_xshm: tried to get unsupported property 8
video_out_xshm: tried to get unsupported property 13
ratio: 17778
video_out_xshm: tried to set unsupported property 8
video_out_xshm: tried to set unsupported property 13
set_speed 1000000
video_out: throwing away image with pts 166092 because it's too old
(diff : 1845).
video jump
video_out: throwing away image with pts 375881 because it's too old
(diff : 4107).
video_out: throwing away image with pts 379057 because it's too old
(diff : 4171).
video_out: throwing away image with pts 384743 because it's too old
(diff : 5685).
video_out: throwing away image with pts 390877 because it's too old
(diff : 10351).
video_out: throwing away image with pts 393793 because it's too old
(diff : 9596).
video jump
video_out: throwing away image with pts 400041 because it's too old
(diff : 14510).
video_out: throwing away image with pts 501830 because it's too old
(diff : 4525).
video_out: throwing away image with pts 507368 because it's too old
(diff : 6187).
video_out: throwing away image with pts 513026 because it's too old
(diff : 11330).
video_out: throwing away image with pts 515711 because it's too old
(diff : 9724).
video_out: throwing away image with pts 521531 because it's too old
(diff : 14705).
video_out: throwing away image with pts 524292 because it's too old
(diff : 11944).
video_out: throwing away image with pts 530257 because it's too old
(diff : 16779).
video_out: throwing away image with pts 535943 because it's too old
(diff : 16134).
video_out: throwing away image with pts 539184 because it's too old
(diff : 16133).
video_out: throwing away image with pts 544993 because it's too old
(diff : 17164).
video_out: throwing away image with pts 548292 because it's too old
(diff : 21065).
video jump
video_out: throwing away image with pts 605648 because it's too old
(diff : 2952).
video_out: throwing away image with pts 609337 because it's too old
(diff : 1785).
video_out: throwing away image with pts 640296 because it's too old
(diff : 4307).
video_out: throwing away image with pts 642698 because it's too old
(diff : 5144).
video_out: throwing away image with pts 647981 because it's too old
(diff : 9222).
video_out: throwing away image with pts 653030 because it's too old
(diff : 10293).
video_out: throwing away image with pts 655968 because it's too old
(diff : 10595).
video_out: throwing away image with pts 661201 because it's too old
(diff : 12563).
video_out: throwing away image with pts 664226 because it's too old
(diff : 16738).
video_out: throwing away image with pts 669626 because it's too old
(diff : 15298).
video_out: throwing away image with pts 672731 because it's too old
(diff : 15441).
set_speed 0
audio_alsa_out: Drain call failed. (err=-11:Resource temporarily unavailable)
set_speed 1000000
audio_out: inserting 17006 0-frames to fill a gap of 31895 pts
video_out: throwing away image with pts 678281 because it's too old
(diff : 19202).
video_out: throwing away image with pts 681457 because it's too old
(diff : 18186).
video_out: throwing away image with pts 687143 because it's too old
(diff : 20781).
video_out: throwing away image with pts 690384 because it's too old
(diff : 23300).
video_out: throwing away image with pts 696193 because it's too old
(diff : 23251).
video_out: throwing away image with pts 702441 because it's too old
(diff : 26723).
video jump
200 frames delivered, 8 frames skipped, 35 frames discarded
video_out: throwing away image with pts 777163 because it's too old
(diff : 2765).
video_out: throwing away image with pts 781531 because it's too old
(diff : 6317).
video_out: throwing away image with pts 786432 because it's too old
(diff : 9696).
video_out: throwing away image with pts 788763 because it's too old
(diff : 12405).
video_out: throwing away image with pts 793898 because it's too old
(diff : 12310).
video_out: throwing away image with pts 799181 because it's too old
(diff : 14948).
video_out: throwing away image with pts 801687 because it's too old
(diff : 17842).
video_out: throwing away image with pts 807168 because it's too old
(diff : 18121).
video_out: throwing away image with pts 809768 because it's too old
(diff : 20922).
video_out: throwing away image with pts 815426 because it's too old
(diff : 21024).
video_out: throwing away image with pts 818111 because it's too old
(diff : 23739).
video_out: throwing away image with pts 823931 because it's too old
(diff : 26920).
video_out: throwing away image with pts 829481 because it's too old
(diff : 27130).
video_out: throwing away image with pts 832657 because it's too old
(diff : 29715).
video_out: throwing away image with pts 838343 because it's too old
(diff : 29789).
video_out: throwing away image with pts 844477 because it's too old
(diff : 33015).
video_out: throwing away image with pts 847393 because it's too old
(diff : 32259).
video_out: throwing away image with pts 853641 because it's too old
(diff : 35731).
video jump
video_out: throwing away image with pts 915668 because it's too old
(diff : 2146).
video_out: throwing away image with pts 919452 because it's too old
(diff : 6282).
video_out: throwing away image with pts 921789 because it's too old
(diff : 8986).
video_out: throwing away image with pts 925880 because it's too old
(diff : 10295).
video_out: throwing away image with pts 928363 because it's too old
(diff : 12854).
video_out: throwing away image with pts 932731 because it's too old
(diff : 13525).
video_out: throwing away image with pts 935345 because it's too old
(diff : 16313).
video_out: throwing away image with pts 939963 because it's too old
(diff : 17453).
video_out: throwing away image with pts 945098 because it's too old
(diff : 20599).
video_out: throwing away image with pts 947540 because it's too old
(diff : 23198).
video_out: throwing away image with pts 952887 because it's too old
(diff : 26131).
video_out: throwing away image with pts 955430 because it's too old
(diff : 28988).
video_out: throwing away image with pts 960968 because it's too old
(diff : 27770).
video_out: throwing away image with pts 963601 because it's too old
(diff : 30538).
input_vdr: execution of rpc command 15 () failed, exiting ...
input_vdr: rpc thread done.
video_out: throwing away image with pts 969311 because it's too old
(diff : 30588).
video_out: throwing away image with pts 972026 because it's too old
(diff : 33273).
video_out: throwing away image with pts 975131 because it's too old
(diff : 32329).
video_out: throwing away image with pts 977892 because it's too old
(diff : 34968).
video_out: throwing away image with pts 980681 because it's too old
(diff : 33618).
[h264 @ 0x2aaaace75800]concealing 5040 DC, 5040 AC, 5040 MV errors
video_out: throwing away image with pts 983857 because it's too old
(diff : 36202).
video_out: throwing away image with pts 986687 because it's too old
(diff : 34094).
ffmpeg_video_dec: error decompressing frame
ffmpeg_video_dec: error decompressing frame
ffmpeg_video_dec: error decompressing frame
ffmpeg_video_dec: error decompressing frame

I don't get video jumping on MPEG 2 pictures, but I do get the
video_out "too old" messages.

When the video jumps, the whole of VDR seems to lock up, i.e. you
can't move the menu selection on the OSD until the video restarts.

Any ideas - or am I hitting some kind of hardware bottleneck here
(dual core 2.13Ghz, 2Gb RAM, IDE disk, NVIDIA 6200LE PCIe graphics @
720p)? Both cores are idle @ around 40%: -

top - 12:17:39 up  1:10,  4 users,  load average: 3.07, 3.31, 3.03
Tasks: 138 total,   2 running, 136 sleeping,   0 stopped,   0 zombie
Cpu0  : 29.3%us,  1.7%sy,  0.0%ni, 67.3%id,  0.0%wa,  1.0%hi,  0.7%si,  0.0%st
Cpu1  : 46.7%us,  0.3%sy,  0.0%ni, 53.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   2063240k total,  1537516k used,   525724k free,   593748k buffers
Swap:  1100412k total,        0k used,  1100412k free,   494464k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 8565 root      15   0  517m 120m  53m S   69  6.0  32:45.80 xine
 8081 root      15   0  155m  82m  55m R    8  4.1   3:18.08 Xorg
 7607 root      15   0  215m  30m 3856 S    2  1.5   0:36.89 vdr

top - 12:18:29 up  1:11,  4 users,  load average: 3.04, 3.28, 3.03
Tasks: 138 total,   3 running, 135 sleeping,   0 stopped,   0 zombie
Cpu0  : 80.3%us,  1.0%sy,  0.0%ni, 17.7%id,  0.0%wa,  0.7%hi,  0.3%si,  0.0%st
Cpu1  : 66.2%us,  1.0%sy,  0.0%ni, 32.8%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   2063240k total,  1537640k used,   525600k free,   593820k buffers
Swap:  1100412k total,        0k used,  1100412k free,   494472k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 8565 root      15   0  517m 120m  53m R  140  6.0  33:50.91 xine
 8081 root      15   0  155m  82m  55m S    8  4.1   3:21.94 Xorg
 7607 root      15   0  215m  30m 3856 S    1  1.5   0:37.70 vdr

HD recordings also show the same symptoms. If you are interested I am
currently uploading a minute of BBC HD recording (140Mb)

Regards,

Morfsta




On 10/24/07, Reinhard Nissl <rnissl@gmx.de> wrote:
> Hi,
>
> Morfsta schrieb:
>
> > The picture was very good, but there was dropped frames that xine
> > reported and the stuttered on occassion and then ran very quickly to
> > catch up. Playing around with the settings in xine (setting threads to
> > 2 etc) didn't really make much difference. However, for the first time
> > I've spent playing with this I was impressed with the picture quality
> > out of VDR. Top reported that the CPU was ~40% idle so I don't know
> > why I saw dropped frames...
>
> Frame duration wasn't set at all in xine-lib for this case. xine-lib-1.2
> contains now a fix for this issue. The fix is part of vdr-xine-0.8.0's
> xine-lib.patch for xine-lib-1.1.8, too.
>
> > One other thing I noticed though was when using XVMC (-V xxmc) to view
> > normal MPEG2 channels the VDR OSD looked terrible (very blockly
> > looking) and playing with the settings in the xine plugin did not make
> > it better. Any recommendations on improving this? When using MPEG4
> > (i.e. software accel)  the OSD was fine.
>
> xxmc's OSD support allows only 16 colors. I assume, you've enabled font
> antialiasing in VDR, which requires much more than 16 colors. This is
> the case for hardware accelerated MPEG2 decoding. For H.264, xxmc falls
> back to xv where there is no such limitation.
>
> You may also want to try to choose unscaled OSD in vdr-xine's setup
> menu, which renders the OSD on top of the video image, using libX11. It
> is therefore not limited to 16 colors but doesn't support OSD
> transparency at all.
>
> Bye.
> --
> Dipl.-Inform. (FH) Reinhard Nissl
> mailto:rnissl@gmx.de
>
> _______________________________________________
> vdr mailing list
> vdr@linuxtv.org
> http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr
>
  
Reinhard Nissl Oct. 25, 2007, 11:40 a.m. UTC | #14
Hi,

Morfsta schrieb:

> I have just tried it on BBC HD (Astra 2 - H264/MBAFF) as well as HD2/5
> (Astra 3 H264/???) and I get video jumping every 2 seconds. Here is
> the [clipped] output from xine (verbose=3): -
> 
> video_out_xshm: video mode depth is 24 (32 bpp), TrueColor, not swapped,

Is there a special reason why you use -V xshm and not -V xv? The later
would do colorspace transformation in hardware.

> HD recordings also show the same symptoms. If you are interested I am
> currently uploading a minute of BBC HD recording (140Mb)

Please provide a link to this recording.

Bye.
  
Morfsta Oct. 25, 2007, 12:20 p.m. UTC | #15
On 10/25/07, Reinhard Nissl <rnissl@gmx.de> wrote:

> Is there a special reason why you use -V xshm and not -V xv? The later
> would do colorspace transformation in hardware.
>

I was just changing settings - I did have xxmc on, but it didn't make
any difference.

> > HD recordings also show the same symptoms. If you are interested I am
> > currently uploading a minute of BBC HD recording (140Mb)
>
> Please provide a link to this recording.
>

Try here: -

http://www.megaupload.com/?d=55JZHZ4A

Thanks.

> Bye.
> --
> Dipl.-Inform. (FH) Reinhard Nissl
> mailto:rnissl@gmx.de
>
> _______________________________________________
> vdr mailing list
> vdr@linuxtv.org
> http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr
>
  
Halim Sahin Oct. 25, 2007, 5:23 p.m. UTC | #16
Hi reinhard,

Is this patch only for (new) radio-recordings???

I tried it but sometimes I am getting a seeg fault when  trying to play
old recordings.
My client vdr is a vdr-1.4.7 with softdevice.
Thanks.
Halim
  
Halim Sahin Oct. 25, 2007, 5:24 p.m. UTC | #17
Sorry wrong thread!
  
Reinhard Nissl Oct. 25, 2007, 9:16 p.m. UTC | #18
Hi,

Morfsta schrieb:

>>> HD recordings also show the same symptoms. If you are interested I am
>>> currently uploading a minute of BBC HD recording (140Mb)
>>
>> Please provide a link to this recording.
>
> Try here: -
> 
> http://www.megaupload.com/?d=55JZHZ4A

Please give the patch on the below mentioned site a try. Your recording
(which uses only interlaced frames) plays properly here when I play it
at 50 % of normal speed (my PC simply isn't fast enough for realtime
decoding).

http://www.vdr-portal.de/board/thread.php?postid=662944#post662944

Bye.
  
Morfsta Oct. 27, 2007, 6:28 p.m. UTC | #19
On 10/25/07, Reinhard Nissl <rnissl@gmx.de> wrote:
> Please give the patch on the below mentioned site a try. Your recording
> (which uses only interlaced frames) plays properly here when I play it
> at 50 % of normal speed (my PC simply isn't fast enough for realtime
> decoding).
>
> http://www.vdr-portal.de/board/thread.php?postid=662944#post662944
>

That has fixed it - BBC HD and HD2/5 (Astra 3) are now playing
smoothly! It is so much better!

Now I have noticed another problem - there is a strange "fuzz" effect
(like tearing, but not exactly the same) on some broadcasts and not on
others. At first I thought it was the graphics setup on fast panning,
but this is not the case - it affects static images also. I saw this
on BBC HD and HD2/5. I managed to capture a snippet of the BBC HD
preview that demonstrates this - it's very strange because clips
before and after this preview snippet were fine again so it must be
something to do with this particular HD recording as part of the
preview...

Here is a link to a short recording (26Mb) demonstrating the problem: -

http://www.megaupload.com/?d=72LCAI2P

Regards,

Morfsta
  
Reinhard Nissl Oct. 31, 2007, 11:51 p.m. UTC | #20
Hi,

Morfsta schrieb:

> Now I have noticed another problem - there is a strange "fuzz" effect
> (like tearing, but not exactly the same) on some broadcasts and not on
> others. At first I thought it was the graphics setup on fast panning,
> but this is not the case - it affects static images also. I saw this
> on BBC HD and HD2/5. I managed to capture a snippet of the BBC HD
> preview that demonstrates this - it's very strange because clips
> before and after this preview snippet were fine again so it must be
> something to do with this particular HD recording as part of the
> preview...
> 
> Here is a link to a short recording (26Mb) demonstrating the problem: -

Please have a look at the patches referenced at
http://www.vdr-portal.de/board/thread.php?postid=664938#post664938

With theses patches, your recording looks much better.

Bye.
  
Morfsta Nov. 1, 2007, 10:40 a.m. UTC | #21
On Oct 31, 2007 11:51 PM, Reinhard Nissl <rnissl@gmx.de> wrote:
> Please have a look at the patches referenced at
> http://www.vdr-portal.de/board/thread.php?postid=664938#post664938
>
> With theses patches, your recording looks much better.

Thanks for your help and assistance Reinhard - I read the thread on
gmane.comp.video.ffmpeg.devel with interest.

I patched ffmpeg and did a make && make install and the recording is
still the same on my system. Do I have to re-compile xine-lib?
  
Reinhard Nissl Nov. 1, 2007, 11:52 a.m. UTC | #22
Hi,

Morfsta schrieb:

> I patched ffmpeg and did a make && make install and the recording is
> still the same on my system. Do I have to re-compile xine-lib?

Sure, because you need the fixes in xine-lib's FFmpeg interfacing file
ff_video_decoder.c, too.

And you'll have to specify a deinterlacer as mentioned on the vdr-portal
page.

Bye.
  
Grégoire Favre Nov. 2, 2007, 10:30 p.m. UTC | #23
On 01/11/2007, Reinhard Nissl <rnissl@gmx.de> wrote:

Hello :-)

> Please have a look at the patches referenced at
> http://www.vdr-portal.de/board/thread.php?postid=664938#post664938
>
> With theses patches, your recording looks much better.

I have recompiled ffmpeg svn with this patch, and xine-lib-1.2 (there
semmes to be included) and also my vdr which now segfault when I try
to
tune to BBC HD :

gdb ./vdr
GNU gdb 6.7.1
Copyright (C) 2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
<http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show
copying"
and "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu"...
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) run -u greg -c /etc/vdr -l 3 -s 'sudo
/usr/local/bin/vdrpoweroff.sh' -P'xine -r'
Starting program: /usr/src/vdr-1.5.10/vdr -u greg -c /etc/vdr -l 3 -s
'sudo /usr/local/bin/vdrpoweroff.sh'
+-P'xine -r'
warning: no loadable sections found in added symbol-file
system-supplied DSO at 0x7fff3effd000
-------------------------
MakePrimaryDevice: 1
=========================
SetVideoFormat: 1
SetVolumeDevice: 255
frame: (0, 0)-(-1, -1), zoom: (1.00, 1.00)
SetVideoWindow: 0, 0, 720, 576, 720, 576
SetVolumeDevice: 255
SetAudioChannelDevice: 0
SetDigitalAudioDevice: 0
SetAudioChannelDevice: 0
frame: (0, 0)-(-1, -1), zoom: (1.00, 1.00)
SetPlayMode: 1
video: synced early
[VM]
vdr-xine: Client connecting ...
vdr-xine: Client connected!
frame: (0, 0)-(720, 576), zoom: (1.00, 1.00)
[vVMA]buffered 20.4 frames (v:28.7, a:20.4)
frame: (0, 0)-(720, 576), zoom: (1.00, 1.00)
SetPlayMode: 0
frame: (0, 0)-(720, 576), zoom: (1.00, 1.00)
SetAudioChannelDevice: 0
SetDigitalAudioDevice: 1
SetAudioChannelDevice: 0
SetPlayMode: 1
audio: synced early
[AMMVframe: (0, 0)-(16, 32), zoom: (1.00, 1.00)
[New LWP 31657]

Program received signal SIGSEGV, Segmentation fault.
[Switching to LWP 31657]
0x00002b0f6c5e47f1 in PluginXine::cXineLib::execFuncOsdDrawBitmap
(this=0x2aaaaea15d98,
    needsScaling=PluginXine::cXineLib::shq, videoWidth=16,
videoHeight=29, xineOsd=<value optimized out>,
    window=0, bitmap=0x2aaaaeb355f0, x=0, y=0, width=672, height=187,
stride=672) at xineLib.c:1010
1010              *c++ = delinearize(c2 / sai) / FIX_POINT_FACTOR;
Current language:  auto; currently c++
(gdb) bt
#0  0x00002b0f6c5e47f1 in PluginXine::cXineLib::execFuncOsdDrawBitmap
(this=0x2aaaaea15d98,
    needsScaling=PluginXine::cXineLib::shq, videoWidth=16,
videoHeight=29, xineOsd=<value optimized out>,
    window=0, bitmap=0x2aaaaeb355f0, x=0, y=0, width=672, height=187,
stride=672) at xineLib.c:1010
#1  0x00002b0f6c5e59bd in PluginXine::cXineLib::sendWindow
(this=0x2aaaaea15d98, xineOsd=0x2aaaaeb35520,
    windowNum=0, bitmap=0x2aaaaeb355f0, videoLeft=0, videoTop=0,
videoWidth=16, videoHeight=32, videoZoomX=100,
    videoZoomY=100, dontOptimize=false) at xineLib.c:1867
#2  0x00002b0f6c5e6fcb in PluginXine::cXineOsd::ReshowCurrentOsd
(this=0x2aaaaeb35520, dontOptimize=false,
    frameLeft=<value optimized out>, frameTop=<value optimized out>,
frameWidth=<value optimized out>,
    frameHeight=<value optimized out>, frameZoomX=100, frameZoomY=100)
at xineOsd.c:136
#3  0x00002b0f6c5dae25 in PluginXine::cXineDevice::reshowCurrentOsd
(this=0x2aaaaea14ad0, dontOptimize=64,
    frameLeft=0, frameTop=0, frameWidth=16, frameHeight=32,
frameZoomX=100, frameZoomY=100) at xineDevice.c:3642
#4  0x00002b0f6c5dae81 in PluginXine::cXineDevice::ReshowCurrentOSD
(this=0x5580, frameLeft=1820500048,
    frameTop=2880, frameWidth=66187264, frameHeight=518684672,
frameZoomX=<value optimized out>, frameZoomY=100)
    at xineDevice.c:3739
#5  0x00002b0f6c5e97ea in PluginXine::cXineRemote::Action
(this=0x2aaaaea147f0) at xineRemote.c:135
#6  0x00000000004bffc5 in cThread::StartThread (Thread=0x2aaaaea14810)
at thread.c:244
#7  0x0000003054406597 in ?? () from /lib/libpthread.so.0
#8  0x0000003053cd406d in clone () from /lib/libc.so.6
#9  0x0000000000000000 in ?? ()

That's with OSD display mode : Blend scaled Auto, with X11 overlay
it don't crash (but that's not nice at all...).

By the way there is another annoying bug with xine-lib :
if you have a timer set, and VDR want to powerdown, but it can't
die to some external reason, you can't control it anymore :

#0  0x000000305440deef in waitpid () from /lib/libpthread.so.0
#1  0x00000000004bfb82 in SystemExec (
    Command=0x2aaaae9ee0c0 "sudo /usr/local/bin/vdrpoweroff.sh
1194037200 121229 317 \"C'EST PAS SORCIER\" 1",
    Detached=true) at thread.c:511
#2  0x00000000004ad2df in cShutdownHandler::CallShutdownCommand
(this=0x7275c0, WakeupTime=1194037200,
    Channel=317, File=0xfecdec "C'EST PAS SORCIER",
UserShutdown=<value optimized out>) at shutdown.c:129
#3  0x00000000004ad8ac in cShutdownHandler::DoShutdown (this=0x7275c0,
Force=false) at shutdown.c:247
#4  0x00000000004c962b in main (argc=14, argv=0x7fffcd756e48) at
vdr.c:1062

Maybe the bug don't come from xine-lib directly, but without xine-lib
it doesn't appear.

Thank,
  
Reinhard Nissl Nov. 3, 2007, 9:24 p.m. UTC | #24
Hi,

Grégoire FAVRE schrieb:

> I have recompiled ffmpeg svn with this patch, and xine-lib-1.2 (there
> semmes to be included) and also my vdr which now segfault when I try
> to
> tune to BBC HD :
[snip]
> That's with OSD display mode : Blend scaled Auto, with X11 overlay
> it don't crash (but that's not nice at all...).

Please have a look at

http://www.vdr-portal.de/board/thread.php?postid=665758#post665758

The new libxine patch should fix this bug.

> By the way there is another annoying bug with xine-lib :
> if you have a timer set, and VDR want to powerdown, but it can't
> die to some external reason, you can't control it anymore :
> 
> #0  0x000000305440deef in waitpid () from /lib/libpthread.so.0
> #1  0x00000000004bfb82 in SystemExec (
>     Command=0x2aaaae9ee0c0 "sudo /usr/local/bin/vdrpoweroff.sh
> 1194037200 121229 317 \"C'EST PAS SORCIER\" 1",
>     Detached=true) at thread.c:511
> #2  0x00000000004ad2df in cShutdownHandler::CallShutdownCommand
> (this=0x7275c0, WakeupTime=1194037200,
>     Channel=317, File=0xfecdec "C'EST PAS SORCIER",
> UserShutdown=<value optimized out>) at shutdown.c:129
> #3  0x00000000004ad8ac in cShutdownHandler::DoShutdown (this=0x7275c0,
> Force=false) at shutdown.c:247
> #4  0x00000000004c962b in main (argc=14, argv=0x7fffcd756e48) at
> vdr.c:1062
> 
> Maybe the bug don't come from xine-lib directly, but without xine-lib
> it doesn't appear.

Maybe I'll have a look at it tomorrow.

Meanwhile, you could have a look at this issue with this gdb command:

	thread apply all bt

It'll tell you the backtrace for all threads.

Bye.
  
Grégoire Favre Nov. 3, 2007, 10:21 p.m. UTC | #25
On Sat, Nov 03, 2007 at 10:24:33PM +0100, Reinhard Nissl wrote:

Hello :-)

> Please have a look at
> 
> http://www.vdr-portal.de/board/thread.php?postid=665758#post665758
> 
> The new libxine patch should fix this bug.

Great, thank !

> Maybe I'll have a look at it tomorrow.
> 
> Meanwhile, you could have a look at this issue with this gdb command:
> 
> 	thread apply all bt
> 
> It'll tell you the backtrace for all threads.

Oops, with the new patched ffmpeg/xine-lib-1.2/vdr-xine it don't
segfault (but I still can't access my VDR after a "shutdown try".

Thank you very much :-)
  

Patch

diff -Nup ../vdr-1.5.10-orig/Makefile ./Makefile
--- ../vdr-1.5.10-orig/Makefile	2007-10-13 11:26:40.000000000 +0200
+++ ./Makefile	2007-10-14 17:22:27.000000000 +0200
@@ -41,7 +42,7 @@  OBJS = audio.o channels.o ci.o config.o 
        lirc.o menu.o menuitems.o nit.o osdbase.o osd.o pat.o player.o plugin.o rcu.o\
        receiver.o recorder.o recording.o remote.o remux.o ringbuffer.o sdt.o sections.o shutdown.o\
        skinclassic.o skins.o skinsttng.o sources.o spu.o status.o svdrp.o themes.o thread.o\
-       timers.o tools.o transfer.o vdr.o videodir.o
+       timers.o tools.o transfer.o vdr.o videodir.o h264parser.o
 
 ifndef NO_KBD
 DEFINES += -DREMOTE_KBD
diff -Nup ../vdr-1.5.10-orig/channels.c ./channels.c
--- ../vdr-1.5.10-orig/channels.c	2007-10-12 16:40:53.000000000 +0200
+++ ./channels.c	2007-10-14 17:22:27.000000000 +0200
@@ -28,60 +28,108 @@  const tChannelParameterMap InversionValu
   };
 
 const tChannelParameterMap BandwidthValues[] = {
-  {   6, BANDWIDTH_6_MHZ },
-  {   7, BANDWIDTH_7_MHZ },
-  {   8, BANDWIDTH_8_MHZ },
-  { 999, BANDWIDTH_AUTO },
+  {   5, DVBFE_BANDWIDTH_5_MHZ },
+  {   6, DVBFE_BANDWIDTH_6_MHZ },
+  {   7, DVBFE_BANDWIDTH_7_MHZ },
+  {   8, DVBFE_BANDWIDTH_8_MHZ },
+  { 999, DVBFE_BANDWIDTH_AUTO },
   { -1 }
   };
 
 const tChannelParameterMap CoderateValues[] = {
-  {   0, FEC_NONE },
-  {  12, FEC_1_2 },
-  {  23, FEC_2_3 },
-  {  34, FEC_3_4 },
-  {  45, FEC_4_5 },
-  {  56, FEC_5_6 },
-  {  67, FEC_6_7 },
-  {  78, FEC_7_8 },
-  {  89, FEC_8_9 },
-  { 999, FEC_AUTO },
+  {   0, DVBFE_FEC_NONE },
+  {  12, DVBFE_FEC_1_2 },
+  {  13, DVBFE_FEC_1_3 },
+  {  14, DVBFE_FEC_1_4 },
+  {  23, DVBFE_FEC_2_3 },
+  {  25, DVBFE_FEC_2_5 },
+  {  34, DVBFE_FEC_3_4 },
+  {  35, DVBFE_FEC_3_5 },
+  {  45, DVBFE_FEC_4_5 },
+  {  56, DVBFE_FEC_5_6 },
+  {  67, DVBFE_FEC_6_7 },
+  {  78, DVBFE_FEC_7_8 },
+  {  89, DVBFE_FEC_8_9 },
+  { 910, DVBFE_FEC_9_10 },
+  { 999, DVBFE_FEC_AUTO },
   { -1 }
   };
 
 const tChannelParameterMap ModulationValues[] = {
-  {   0, QPSK },
-  {  16, QAM_16 },
-  {  32, QAM_32 },
-  {  64, QAM_64 },
-  { 128, QAM_128 },
-  { 256, QAM_256 },
-  { 999, QAM_AUTO },
+  {   0, DVBFE_MOD_NONE },
+  {   4, DVBFE_MOD_QAM4 },
+  {  16, DVBFE_MOD_QAM16 },
+  {  32, DVBFE_MOD_QAM32 },
+  {  64, DVBFE_MOD_QAM64 },
+  { 128, DVBFE_MOD_QAM128 },
+  { 256, DVBFE_MOD_QAM256 },
+  { 512, DVBFE_MOD_QAM512 },
+  {1024, DVBFE_MOD_QAM1024 },
+  {   1, DVBFE_MOD_BPSK },
+  {   2, DVBFE_MOD_QPSK },
+  {   3, DVBFE_MOD_OQPSK },
+  {   5, DVBFE_MOD_8PSK },
+  {   6, DVBFE_MOD_16APSK },
+  {   7, DVBFE_MOD_32APSK },
+  {   8, DVBFE_MOD_OFDM },
+  {   9, DVBFE_MOD_COFDM },
+  {  10, DVBFE_MOD_VSB8 },
+  {  11, DVBFE_MOD_VSB16 },
+  { 998, DVBFE_MOD_QAMAUTO },
+  { 999, DVBFE_MOD_AUTO },
+  { -1 }
+  };
+
+const tChannelParameterMap ModulationSystemValues[] = {
+  {   0, DVBFE_DELSYS_DVBS },
+  {   1, DVBFE_DELSYS_DVBS2 },
   { -1 }
   };
 
 const tChannelParameterMap TransmissionValues[] = {
-  {   2, TRANSMISSION_MODE_2K },
-  {   8, TRANSMISSION_MODE_8K },
-  { 999, TRANSMISSION_MODE_AUTO },
+  {   2, DVBFE_TRANSMISSION_MODE_2K },
+  {   4, DVBFE_TRANSMISSION_MODE_4K },
+  {   8, DVBFE_TRANSMISSION_MODE_8K },
+  { 999, DVBFE_TRANSMISSION_MODE_AUTO },
   { -1 }
   };
 
 const tChannelParameterMap GuardValues[] = {
-  {   4, GUARD_INTERVAL_1_4 },
-  {   8, GUARD_INTERVAL_1_8 },
-  {  16, GUARD_INTERVAL_1_16 },
-  {  32, GUARD_INTERVAL_1_32 },
-  { 999, GUARD_INTERVAL_AUTO },
+  {   4, DVBFE_GUARD_INTERVAL_1_4 },
+  {   8, DVBFE_GUARD_INTERVAL_1_8 },
+  {  16, DVBFE_GUARD_INTERVAL_1_16 },
+  {  32, DVBFE_GUARD_INTERVAL_1_32 },
+  { 999, DVBFE_GUARD_INTERVAL_AUTO },
   { -1 }
   };
 
 const tChannelParameterMap HierarchyValues[] = {
-  {   0, HIERARCHY_NONE },
-  {   1, HIERARCHY_1 },
-  {   2, HIERARCHY_2 },
-  {   4, HIERARCHY_4 },
-  { 999, HIERARCHY_AUTO },
+  {   0, DVBFE_HIERARCHY_OFF },
+  {   1, DVBFE_HIERARCHY_ON },
+  { 999, DVBFE_HIERARCHY_AUTO },
+  { -1 }
+  };
+
+const tChannelParameterMap AlphaValues[] = {
+  {   0, 0 },
+  {   1, DVBFE_ALPHA_1 },
+  {   2, DVBFE_ALPHA_2 },
+  {   4, DVBFE_ALPHA_4 },
+  { -1 }
+  };
+
+const tChannelParameterMap PriorityValues[] = {
+  {   0, DVBFE_STREAM_PRIORITY_HP },
+  {   1, DVBFE_STREAM_PRIORITY_LP },
+  { -1 }
+  };
+
+//XXX rollOff really necessary? -> if so, also in channels.conf parameters and cMenuEditChannel!
+const tChannelParameterMap RollOffValues[] = {
+  {   0, DVBFE_ROLLOFF_UNKNOWN },
+  {  20, DVBFE_ROLLOFF_20 },
+  {  25, DVBFE_ROLLOFF_25 },
+  {  35, DVBFE_ROLLOFF_35 },
   { -1 }
   };
 
@@ -168,13 +216,15 @@  cChannel::cChannel(void)
   portalName = strdup("");
   memset(&__BeginData__, 0, (char *)&__EndData__ - (char *)&__BeginData__);
   inversion    = INVERSION_AUTO;
-  bandwidth    = BANDWIDTH_AUTO;
-  coderateH    = FEC_AUTO;
-  coderateL    = FEC_AUTO;
-  modulation   = QAM_AUTO;
-  transmission = TRANSMISSION_MODE_AUTO;
-  guard        = GUARD_INTERVAL_AUTO;
-  hierarchy    = HIERARCHY_AUTO;
+  bandwidth    = DVBFE_BANDWIDTH_AUTO;
+  coderateH    = DVBFE_FEC_AUTO;
+  coderateL    = DVBFE_FEC_AUTO;
+  modulation   = DVBFE_MOD_AUTO;
+  modulationSystem = DVBFE_DELSYS_DVBS;
+  transmission = DVBFE_TRANSMISSION_MODE_AUTO;
+  guard        = DVBFE_GUARD_INTERVAL_AUTO;
+  hierarchy    = DVBFE_HIERARCHY_AUTO;
+  rollOff      = DVBFE_ROLLOFF_UNKNOWN;//XXX rollOff really necessary?
   modification = CHANNELMOD_NONE;
   schedule     = NULL;
   linkChannels = NULL;
@@ -277,13 +327,17 @@  void cChannel::CopyTransponderData(const
      coderateH    = Channel->coderateH;
      coderateL    = Channel->coderateL;
      modulation   = Channel->modulation;
+     modulationSystem = Channel->modulationSystem;
      transmission = Channel->transmission;
      guard        = Channel->guard;
      hierarchy    = Channel->hierarchy;
+     rollOff      = Channel->rollOff;
+     alpha        = Channel->alpha;
+     priority     = Channel->priority;
      }
 }
 
-bool cChannel::SetSatTransponderData(int Source, int Frequency, char Polarization, int Srate, int CoderateH)
+bool cChannel::SetSatTransponderData(int Source, int Frequency, char Polarization, int Srate, int CoderateH, int Modulation, int ModulationSystem, int RollOff)//XXX rollOff really necessary?
 {
   // Workarounds for broadcaster stupidity:
   // Some providers broadcast the transponder frequency of their channels with two different
@@ -297,9 +351,9 @@  bool cChannel::SetSatTransponderData(int
   if (abs(srate - Srate) <= 1)
      Srate = srate;
 
-  if (source != Source || frequency != Frequency || polarization != Polarization || srate != Srate || coderateH != CoderateH) {
+  if (source != Source || frequency != Frequency || polarization != Polarization || srate != Srate || coderateH != CoderateH || modulation != Modulation || modulationSystem != ModulationSystem || rollOff != RollOff) {
      if (Number()) {
-        dsyslog("changing transponder data of channel %d from %s:%d:%c:%d:%d to %s:%d:%c:%d:%d", Number(), *cSource::ToString(source), frequency, polarization, srate, coderateH, *cSource::ToString(Source), Frequency, Polarization, Srate, CoderateH);
+        dsyslog("changing transponder data of channel %d from %s:%d:%c:%d:%d:%d:%d:%d to %s:%d:%c:%d:%d:%d:%d:%d", Number(), *cSource::ToString(source), frequency, polarization, srate, coderateH, modulation, modulationSystem, rollOff, *cSource::ToString(Source), Frequency, Polarization, Srate, CoderateH, Modulation, ModulationSystem, RollOff);
         modification |= CHANNELMOD_TRANSP;
         Channels.SetModified();
         }
@@ -308,7 +362,9 @@  bool cChannel::SetSatTransponderData(int
      polarization = Polarization;
      srate = Srate;
      coderateH = CoderateH;
-     modulation = QPSK;
+     modulation = Modulation;
+     modulationSystem = ModulationSystem;
+     rollOff = RollOff;
      schedule = NULL;
      }
   return true;
@@ -332,11 +388,11 @@  bool cChannel::SetCableTransponderData(i
   return true;
 }
 
-bool cChannel::SetTerrTransponderData(int Source, int Frequency, int Bandwidth, int Modulation, int Hierarchy, int CoderateH, int CoderateL, int Guard, int Transmission)
+bool cChannel::SetTerrTransponderData(int Source, int Frequency, int Bandwidth, int Modulation, int Hierarchy, int CoderateH, int CoderateL, int Guard, int Transmission, int Alpha, int Priority)
 {
-  if (source != Source || frequency != Frequency || bandwidth != Bandwidth || modulation != Modulation || hierarchy != Hierarchy || coderateH != CoderateH || coderateL != CoderateL || guard != Guard || transmission != Transmission) {
+  if (source != Source || frequency != Frequency || bandwidth != Bandwidth || modulation != Modulation || hierarchy != Hierarchy || coderateH != CoderateH || coderateL != CoderateL || guard != Guard || transmission != Transmission || alpha != Alpha || priority != Priority) {
      if (Number()) {
-        dsyslog("changing transponder data of channel %d from %s:%d:%d:%d:%d:%d:%d:%d:%d to %s:%d:%d:%d:%d:%d:%d:%d:%d", Number(), *cSource::ToString(source), frequency, bandwidth, modulation, hierarchy, coderateH, coderateL, guard, transmission, *cSource::ToString(Source), Frequency, Bandwidth, Modulation, Hierarchy, CoderateH, CoderateL, Guard, Transmission);
+        dsyslog("changing transponder data of channel %d from %s:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d to %s:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d", Number(), *cSource::ToString(source), frequency, bandwidth, modulation, hierarchy, coderateH, coderateL, guard, transmission, alpha, priority, *cSource::ToString(Source), Frequency, Bandwidth, Modulation, Hierarchy, CoderateH, CoderateL, Guard, Transmission, Alpha, Priority);
         modification |= CHANNELMOD_TRANSP;
         Channels.SetModified();
         }
@@ -349,6 +405,8 @@  bool cChannel::SetTerrTransponderData(in
      coderateL = CoderateL;
      guard = Guard;
      transmission = Transmission;
+     alpha = Alpha;
+     priority = Priority;
      schedule = NULL;
      }
   return true;
@@ -597,14 +655,18 @@  cString cChannel::ParametersToString(voi
   char *q = buffer;
   *q = 0;
   ST(" S ")  q += sprintf(q, "%c", polarization);
+  ST("  T")  q += PrintParameter(q, 'A', MapToUser(alpha, AlphaValues));
   ST("CST")  q += PrintParameter(q, 'I', MapToUser(inversion, InversionValues));
   ST("CST")  q += PrintParameter(q, 'C', MapToUser(coderateH, CoderateValues));
   ST("  T")  q += PrintParameter(q, 'D', MapToUser(coderateL, CoderateValues));
-  ST("C T")  q += PrintParameter(q, 'M', MapToUser(modulation, ModulationValues));
+  ST("CST")  q += PrintParameter(q, 'M', MapToUser(modulation, ModulationValues));
+  ST(" S ")  q += PrintParameter(q, 'S', MapToUser(modulationSystem, ModulationSystemValues));
   ST("  T")  q += PrintParameter(q, 'B', MapToUser(bandwidth, BandwidthValues));
   ST("  T")  q += PrintParameter(q, 'T', MapToUser(transmission, TransmissionValues));
   ST("  T")  q += PrintParameter(q, 'G', MapToUser(guard, GuardValues));
   ST("  T")  q += PrintParameter(q, 'Y', MapToUser(hierarchy, HierarchyValues));
+  ST("  T")  q += PrintParameter(q, 'P', MapToUser(priority, PriorityValues));
+  ST(" S ")  q += PrintParameter(q, 'Z', MapToUser(rollOff, RollOffValues));
   return buffer;
 }
 
@@ -628,6 +690,7 @@  bool cChannel::StringToParameters(const 
 {
   while (s && *s) {
         switch (toupper(*s)) {
+          case 'A': s = ParseParameter(s, alpha, AlphaValues); break;
           case 'B': s = ParseParameter(s, bandwidth, BandwidthValues); break;
           case 'C': s = ParseParameter(s, coderateH, CoderateValues); break;
           case 'D': s = ParseParameter(s, coderateL, CoderateValues); break;
@@ -636,10 +699,13 @@  bool cChannel::StringToParameters(const 
           case 'I': s = ParseParameter(s, inversion, InversionValues); break;
           case 'L': polarization = *s++; break;
           case 'M': s = ParseParameter(s, modulation, ModulationValues); break;
+          case 'P': s = ParseParameter(s, priority, PriorityValues); break;
           case 'R': polarization = *s++; break;
+          case 'S': s = ParseParameter(s, modulationSystem, ModulationSystemValues); break;
           case 'T': s = ParseParameter(s, transmission, TransmissionValues); break;
           case 'V': polarization = *s++; break;
           case 'Y': s = ParseParameter(s, hierarchy, HierarchyValues); break;
+          case 'Z': s = ParseParameter(s, rollOff, RollOffValues); break;
           default: esyslog("ERROR: unknown parameter key '%c'", *s);
                    return false;
           }
diff -Nup ../vdr-1.5.10-orig/channels.h ./channels.h
--- ../vdr-1.5.10-orig/channels.h	2007-09-02 12:23:11.000000000 +0200
+++ ./channels.h	2007-10-14 17:22:27.000000000 +0200
@@ -47,6 +47,16 @@ 
 #define CA_ENCRYPTED_MIN 0x0100
 #define CA_ENCRYPTED_MAX 0xFFFF
 
+// VPID can be in the range 0...8191. Offsets of 10000 are used to indicate special video codings.
+#define VPID_OFFSET_BASE         10000
+#define VPID_FROM_ANY(pid)       ((pid) % VPID_OFFSET_BASE) // returns the plain VPID
+#define VPID_TO_XXX(pid, offset) (pid + offset)
+#define VPID_IS_XXX(pid, offset) ((pid - VPID_FROM_ANY(pid)) == offset)
+// 1. special video coding: H.264
+#define VPID_OFFSET_H264         (1 * VPID_OFFSET_BASE)
+#define VPID_TO_H264(pid)        VPID_TO_XXX(pid, VPID_OFFSET_H264)
+#define VPID_IS_H264(pid)        VPID_IS_XXX(pid, VPID_OFFSET_H264)
+
 struct tChannelParameterMap {
   int userValue;
   int driverValue;
@@ -58,13 +68,17 @@  int MapToDriver(int Value, const tChanne
 int UserIndex(int Value, const tChannelParameterMap *Map);
 int DriverIndex(int Value, const tChannelParameterMap *Map);
 
+extern const tChannelParameterMap AlphaValues[];
 extern const tChannelParameterMap InversionValues[];
 extern const tChannelParameterMap BandwidthValues[];
 extern const tChannelParameterMap CoderateValues[];
 extern const tChannelParameterMap ModulationValues[];
+extern const tChannelParameterMap ModulationSystemValues[];
 extern const tChannelParameterMap TransmissionValues[];
 extern const tChannelParameterMap GuardValues[];
 extern const tChannelParameterMap HierarchyValues[];
+extern const tChannelParameterMap RollOffValues[];
+extern const tChannelParameterMap PriorityValues[];
 
 struct tChannelID {
 private:
@@ -140,9 +154,13 @@  private:
   int coderateH;
   int coderateL;
   int modulation;
+  int modulationSystem;
   int transmission;
   int guard;
   int hierarchy;
+  int alpha;
+  int priority;
+  int rollOff;//XXX rollOff really necessary?
   int __EndData__;
   int modification;
   mutable const cSchedule *schedule;
@@ -190,13 +208,17 @@  public:
   bool GroupSep(void) const { return groupSep; }
   char Polarization(void) const { return polarization; }
   int Inversion(void) const { return inversion; }
+  int Alpha(void) const { return alpha; }
   int Bandwidth(void) const { return bandwidth; }
   int CoderateH(void) const { return coderateH; }
   int CoderateL(void) const { return coderateL; }
   int Modulation(void) const { return modulation; }
+  int ModulationSystem(void) const { return modulationSystem; }
+  int RollOff(void) const { return rollOff; }
   int Transmission(void) const { return transmission; }
   int Guard(void) const { return guard; }
   int Hierarchy(void) const { return hierarchy; }
+  int Priority(void) const { return priority; }
   const cLinkChannels* LinkChannels(void) const { return linkChannels; }
   const cChannel *RefChannel(void) const { return refChannel; }
   bool IsCable(void) const { return cSource::IsCable(source); }
@@ -206,9 +228,9 @@  public:
   bool HasTimer(void) const;
   int Modification(int Mask = CHANNELMOD_ALL);
   void CopyTransponderData(const cChannel *Channel);
-  bool SetSatTransponderData(int Source, int Frequency, char Polarization, int Srate, int CoderateH);
+  bool SetSatTransponderData(int Source, int Frequency, char Polarization, int Srate, int CoderateH, int Modulation, int ModulationSystem, int RollOff);
   bool SetCableTransponderData(int Source, int Frequency, int Modulation, int Srate, int CoderateH);
-  bool SetTerrTransponderData(int Source, int Frequency, int Bandwidth, int Modulation, int Hierarchy, int CodeRateH, int CodeRateL, int Guard, int Transmission);
+  bool SetTerrTransponderData(int Source, int Frequency, int Bandwidth, int Modulation, int Hierarchy, int CodeRateH, int CodeRateL, int Guard, int Transmission, int Alpha, int Priority);
   void SetId(int Nid, int Tid, int Sid, int Rid = 0);
   void SetName(const char *Name, const char *ShortName, const char *Provider);
   void SetPortalName(const char *PortalName);
diff -Nup ../vdr-1.5.10-orig/ci.c ./ci.c
--- ../vdr-1.5.10-orig/ci.c	2007-04-30 15:02:49.000000000 +0200
+++ ./ci.c	2007-08-31 21:08:30.000000000 +0200
@@ -1880,7 +1880,7 @@  void cCamSlot::AddChannel(const cChannel
   source = Channel->Source();
   transponder = Channel->Transponder();
   if (Channel->Ca() >= CA_ENCRYPTED_MIN) {
-     AddPid(Channel->Sid(), Channel->Vpid(), STREAM_TYPE_VIDEO);
+     AddPid(Channel->Sid(), VPID_FROM_ANY(Channel->Vpid()), STREAM_TYPE_VIDEO);
      for (const int *Apid = Channel->Apids(); *Apid; Apid++)
          AddPid(Channel->Sid(), *Apid, STREAM_TYPE_AUDIO);
      for (const int *Dpid = Channel->Dpids(); *Dpid; Dpid++)
@@ -1901,7 +1901,7 @@  bool cCamSlot::CanDecrypt(const cChannel
   if (cas && cas->RepliesToQuery()) {
      cCiCaPmt CaPmt(CPCI_QUERY, Channel->Source(), Channel->Transponder(), Channel->Sid(), GetCaSystemIds());
      CaPmt.SetListManagement(CPLM_ADD); // WORKAROUND: CPLM_ONLY doesn't work with Alphacrypt 3.09 (deletes existing CA_PMTs)
-     CaPmt.AddPid(Channel->Vpid(), STREAM_TYPE_VIDEO);
+     CaPmt.AddPid(VPID_FROM_ANY(Channel->Vpid()), STREAM_TYPE_VIDEO);
      for (const int *Apid = Channel->Apids(); *Apid; Apid++)
          CaPmt.AddPid(*Apid, STREAM_TYPE_AUDIO);
      for (const int *Dpid = Channel->Dpids(); *Dpid; Dpid++)
diff -Nup ../vdr-1.5.10-orig/device.c ./device.c
--- ../vdr-1.5.10-orig/device.c	2007-10-14 15:09:19.000000000 +0200
+++ ./device.c	2007-10-14 17:25:56.000000000 +0200
@@ -821,7 +821,7 @@  eSetChannelResult cDevice::SetChannel(co
            }
         for (int i = 0; i < MAXSPIDS; i++)
             SetAvailableTrack(ttSubtitle, i, Channel->Spid(i), Channel->Slang(i));
-        if (!NeedsTransferMode)
+        if (!NeedsTransferMode || GetCurrentAudioTrack() == ttNone)
            EnsureAudioTrack(true);
         EnsureSubtitleTrack();
         }
diff -Nup ../vdr-1.5.10-orig/dvbdevice.c ./dvbdevice.c
--- ../vdr-1.5.10-orig/dvbdevice.c	2007-10-14 14:56:03.000000000 +0200
+++ ./dvbdevice.c	2007-10-14 17:22:27.000000000 +0200
@@ -76,7 +76,7 @@  private:
   int tuneTimeout;
   int lockTimeout;
   time_t lastTimeoutReport;
-  fe_type_t frontendType;
+  dvbfe_delsys frontendType;
   cChannel channel;
   const char *diseqcCommands;
   eTunerStatus tunerStatus;
@@ -87,14 +87,14 @@  private:
   bool SetFrontend(void);
   virtual void Action(void);
 public:
-  cDvbTuner(int Fd_Frontend, int CardIndex, fe_type_t FrontendType);
+  cDvbTuner(int Fd_Frontend, int CardIndex, dvbfe_delsys FrontendType);
   virtual ~cDvbTuner();
   bool IsTunedTo(const cChannel *Channel) const;
   void Set(const cChannel *Channel, bool Tune);
   bool Locked(int TimeoutMs = 0);
   };
 
-cDvbTuner::cDvbTuner(int Fd_Frontend, int CardIndex, fe_type_t FrontendType)
+cDvbTuner::cDvbTuner(int Fd_Frontend, int CardIndex, dvbfe_delsys FrontendType)
 {
   fd_frontend = Fd_Frontend;
   cardIndex = CardIndex;
@@ -104,7 +104,7 @@  cDvbTuner::cDvbTuner(int Fd_Frontend, in
   lastTimeoutReport = 0;
   diseqcCommands = NULL;
   tunerStatus = tsIdle;
-  if (frontendType == FE_QPSK)
+  if (frontendType & (DVBFE_DELSYS_DVBS | DVBFE_DELSYS_DVBS2))
      CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); // must explicitly turn on LNB power
   SetDescription("tuner on device %d", cardIndex + 1);
   Start();
@@ -173,114 +173,165 @@  static unsigned int FrequencyToHz(unsign
 
 bool cDvbTuner::SetFrontend(void)
 {
-  dvb_frontend_parameters Frontend;
-
+  dvbfe_params Frontend;
   memset(&Frontend, 0, sizeof(Frontend));
 
-  switch (frontendType) {
-    case FE_QPSK: { // DVB-S
-
-         unsigned int frequency = channel.Frequency();
-
-         if (Setup.DiSEqC) {
-            cDiseqc *diseqc = Diseqcs.Get(channel.Source(), channel.Frequency(), channel.Polarization());
-            if (diseqc) {
-               if (diseqc->Commands() && (!diseqcCommands || strcmp(diseqcCommands, diseqc->Commands()) != 0)) {
-                  cDiseqc::eDiseqcActions da;
-                  for (char *CurrentAction = NULL; (da = diseqc->Execute(&CurrentAction)) != cDiseqc::daNone; ) {
-                      switch (da) {
-                        case cDiseqc::daNone:      break;
-                        case cDiseqc::daToneOff:   CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF)); break;
-                        case cDiseqc::daToneOn:    CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_ON)); break;
-                        case cDiseqc::daVoltage13: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); break;
-                        case cDiseqc::daVoltage18: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_18)); break;
-                        case cDiseqc::daMiniA:     CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_A)); break;
-                        case cDiseqc::daMiniB:     CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_B)); break;
-                        case cDiseqc::daCodes: {
-                             int n = 0;
-                             uchar *codes = diseqc->Codes(n);
-                             if (codes) {
-                                struct dvb_diseqc_master_cmd cmd;
-                                memcpy(cmd.msg, codes, min(n, int(sizeof(cmd.msg))));
-                                cmd.msg_len = n;
-                                CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd));
-                                }
-                             }
-                             break;
-                        }
-                      }
-                  diseqcCommands = diseqc->Commands();
+  if (frontendType & (DVBFE_DELSYS_DVBS | DVBFE_DELSYS_DVBS2)) { // DVB-S
+     unsigned int frequency = channel.Frequency();
+     if (Setup.DiSEqC) {
+        cDiseqc *diseqc = Diseqcs.Get(channel.Source(), channel.Frequency(), channel.Polarization());
+        if (diseqc) {
+           if (diseqc->Commands() && (!diseqcCommands || strcmp(diseqcCommands, diseqc->Commands()) != 0)) {
+fprintf(stderr, "DiSEqC: %s\n", diseqc->Commands());
+              cDiseqc::eDiseqcActions da;
+              for (char *CurrentAction = NULL; (da = diseqc->Execute(&CurrentAction)) != cDiseqc::daNone; ) {
+                  switch (da) {
+                    case cDiseqc::daNone:      break;
+                    case cDiseqc::daToneOff:   CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF)); break;
+                    case cDiseqc::daToneOn:    CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_ON)); break;
+                    case cDiseqc::daVoltage13: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); break;
+                    case cDiseqc::daVoltage18: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_18)); break;
+                    case cDiseqc::daMiniA:     CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_A)); break;
+                    case cDiseqc::daMiniB:     CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_B)); break;
+                    case cDiseqc::daCodes: {
+                         int n = 0;
+                         uchar *codes = diseqc->Codes(n);
+                         if (codes) {
+                            struct dvb_diseqc_master_cmd cmd;
+                            memcpy(cmd.msg, codes, min(n, int(sizeof(cmd.msg))));
+                            cmd.msg_len = n;
+                            CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd));
+                            }
+                         }
+                         break;
+                    }
                   }
-               frequency -= diseqc->Lof();
-               }
-            else {
-               esyslog("ERROR: no DiSEqC parameters found for channel %d", channel.Number());
-               return false;
-               }
-            }
-         else {
-            int tone = SEC_TONE_OFF;
-
-            if (frequency < (unsigned int)Setup.LnbSLOF) {
-               frequency -= Setup.LnbFrequLo;
-               tone = SEC_TONE_OFF;
-               }
-            else {
-               frequency -= Setup.LnbFrequHi;
-               tone = SEC_TONE_ON;
-               }
-            int volt = (channel.Polarization() == 'v' || channel.Polarization() == 'V' || channel.Polarization() == 'r' || channel.Polarization() == 'R') ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18;
-            CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, volt));
-            CHECK(ioctl(fd_frontend, FE_SET_TONE, tone));
-            }
-
-         frequency = abs(frequency); // Allow for C-band, where the frequency is less than the LOF
-         Frontend.frequency = frequency * 1000UL;
-         Frontend.inversion = fe_spectral_inversion_t(channel.Inversion());
-         Frontend.u.qpsk.symbol_rate = channel.Srate() * 1000UL;
-         Frontend.u.qpsk.fec_inner = fe_code_rate_t(channel.CoderateH());
-
-         tuneTimeout = DVBS_TUNE_TIMEOUT;
-         lockTimeout = DVBS_LOCK_TIMEOUT;
-         }
-         break;
-    case FE_QAM: { // DVB-C
-
-         // Frequency and symbol rate:
-
-         Frontend.frequency = FrequencyToHz(channel.Frequency());
-         Frontend.inversion = fe_spectral_inversion_t(channel.Inversion());
-         Frontend.u.qam.symbol_rate = channel.Srate() * 1000UL;
-         Frontend.u.qam.fec_inner = fe_code_rate_t(channel.CoderateH());
-         Frontend.u.qam.modulation = fe_modulation_t(channel.Modulation());
-
-         tuneTimeout = DVBC_TUNE_TIMEOUT;
-         lockTimeout = DVBC_LOCK_TIMEOUT;
-         }
-         break;
-    case FE_OFDM: { // DVB-T
-
-         // Frequency and OFDM paramaters:
-
-         Frontend.frequency = FrequencyToHz(channel.Frequency());
-         Frontend.inversion = fe_spectral_inversion_t(channel.Inversion());
-         Frontend.u.ofdm.bandwidth = fe_bandwidth_t(channel.Bandwidth());
-         Frontend.u.ofdm.code_rate_HP = fe_code_rate_t(channel.CoderateH());
-         Frontend.u.ofdm.code_rate_LP = fe_code_rate_t(channel.CoderateL());
-         Frontend.u.ofdm.constellation = fe_modulation_t(channel.Modulation());
-         Frontend.u.ofdm.transmission_mode = fe_transmit_mode_t(channel.Transmission());
-         Frontend.u.ofdm.guard_interval = fe_guard_interval_t(channel.Guard());
-         Frontend.u.ofdm.hierarchy_information = fe_hierarchy_t(channel.Hierarchy());
-
-         tuneTimeout = DVBT_TUNE_TIMEOUT;
-         lockTimeout = DVBT_LOCK_TIMEOUT;
-         }
-         break;
-    default:
-         esyslog("ERROR: attempt to set channel with unknown DVB frontend type");
-         return false;
-    }
-  if (ioctl(fd_frontend, FE_SET_FRONTEND, &Frontend) < 0) {
+              diseqcCommands = diseqc->Commands();
+              }
+           frequency -= diseqc->Lof();
+           }
+        else {
+           esyslog("ERROR: no DiSEqC parameters found for channel %d", channel.Number());
+           return false;
+           }
+        }
+     else {
+        int tone = SEC_TONE_OFF;
+        if (frequency < (unsigned int)Setup.LnbSLOF) {
+           frequency -= Setup.LnbFrequLo;
+           tone = SEC_TONE_OFF;
+           }
+        else {
+           frequency -= Setup.LnbFrequHi;
+           tone = SEC_TONE_ON;
+           }
+        int volt = (channel.Polarization() == 'v' || channel.Polarization() == 'V' || channel.Polarization() == 'r' || channel.Polarization() == 'R') ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18;
+        CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, volt));
+        CHECK(ioctl(fd_frontend, FE_SET_TONE, tone));
+        }
+     frequency = abs(frequency); // Allow for C-band, where the frequency is less than the LOF
+     Frontend.frequency = frequency * 1000UL;
+     Frontend.inversion = fe_spectral_inversion_t(channel.Inversion());
+
+     dvbfe_info feinfo;
+     if (channel.ModulationSystem() == DVBFE_DELSYS_DVBS) {
+        dsyslog("set DVB-S");
+        feinfo.delivery = DVBFE_DELSYS_DVBS;
+        CHECK(ioctl(fd_frontend, DVBFE_GET_INFO, &feinfo)); //switch system
+
+        Frontend.delivery = DVBFE_DELSYS_DVBS;
+        Frontend.inversion = fe_spectral_inversion_t(channel.Inversion());
+        Frontend.delsys.dvbs.modulation = dvbfe_modulation(channel.Modulation());
+        Frontend.delsys.dvbs.symbol_rate = channel.Srate() * 1000UL;
+        Frontend.delsys.dvbs.fec = dvbfe_fec(channel.CoderateH());
+        }
+     else {
+        dsyslog("set DVB-S2");
+        feinfo.delivery = DVBFE_DELSYS_DVBS2;
+        CHECK(ioctl(fd_frontend, DVBFE_GET_INFO, &feinfo)); //switch system
+
+        Frontend.delivery = DVBFE_DELSYS_DVBS2;
+        Frontend.inversion = fe_spectral_inversion_t(channel.Inversion());
+        Frontend.delsys.dvbs2.modulation = dvbfe_modulation(channel.Modulation());
+        Frontend.delsys.dvbs2.symbol_rate = channel.Srate() * 1000UL;
+        Frontend.delsys.dvbs2.fec = dvbfe_fec(channel.CoderateH());
+        Frontend.delsys.dvbs2.rolloff = dvbfe_rolloff(channel.RollOff());
+        }
+     tuneTimeout = DVBS_TUNE_TIMEOUT;
+     lockTimeout = DVBS_LOCK_TIMEOUT;
+     }
+  else if (frontendType & DVBFE_DELSYS_DVBC) { // DVB-C
+     dvbfe_info feinfo;
+     feinfo.delivery = DVBFE_DELSYS_DVBC;
+     CHECK(ioctl(fd_frontend, DVBFE_GET_INFO, &feinfo)); //switch system
+
+     Frontend.delivery = DVBFE_DELSYS_DVBC;
+     Frontend.frequency = FrequencyToHz(channel.Frequency());
+     Frontend.inversion = fe_spectral_inversion_t(channel.Inversion());
+     Frontend.delsys.dvbc.symbol_rate = channel.Srate() * 1000UL;
+     Frontend.delsys.dvbc.fec = dvbfe_fec(channel.CoderateH());
+     Frontend.delsys.dvbc.modulation = dvbfe_modulation(channel.Modulation());
+
+     tuneTimeout = DVBC_TUNE_TIMEOUT;
+     lockTimeout = DVBC_LOCK_TIMEOUT;
+     }
+  else if (frontendType & DVBFE_DELSYS_DVBT) { // DVB-T
+     dvbfe_info feinfo;
+     feinfo.delivery = DVBFE_DELSYS_DVBT;
+     CHECK(ioctl(fd_frontend, DVBFE_GET_INFO, &feinfo)); //switch system
+
+     Frontend.delivery = DVBFE_DELSYS_DVBT;
+     Frontend.frequency = FrequencyToHz(channel.Frequency());
+     Frontend.inversion = fe_spectral_inversion_t(channel.Inversion());
+     Frontend.delsys.dvbt.bandwidth = dvbfe_bandwidth(channel.Bandwidth());
+     Frontend.delsys.dvbt.code_rate_HP = dvbfe_fec(channel.CoderateH());
+     Frontend.delsys.dvbt.code_rate_LP = dvbfe_fec(channel.CoderateL());
+     Frontend.delsys.dvbt.constellation = dvbfe_modulation(channel.Modulation());
+     Frontend.delsys.dvbt.transmission_mode = dvbfe_transmission_mode(channel.Transmission());
+     Frontend.delsys.dvbt.guard_interval = dvbfe_guard_interval(channel.Guard());
+     Frontend.delsys.dvbt.hierarchy = dvbfe_hierarchy(channel.Hierarchy());
+     Frontend.delsys.dvbt.alpha = dvbfe_alpha(channel.Alpha());
+     Frontend.delsys.dvbt.priority = dvbfe_stream_priority(channel.Priority());
+
+     tuneTimeout = DVBT_TUNE_TIMEOUT;
+     lockTimeout = DVBT_LOCK_TIMEOUT;
+     }
+/* XXX
+  else if (frontendType & DVBFE_DELSYS_DVBH) { // DVB-H
+     Frontend.delivery = DVBFE_DELSYS_DVBH;
+     Frontend.frequency = FrequencyToHz(channel.Frequency());
+     Frontend.inversion = fe_spectral_inversion_t(channel.Inversion());
+
+     Frontend.delsys.dvbh.bandwidth = dvbfe_bandwidth(channel.Bandwidth());
+     Frontend.delsys.dvbh.code_rate_HP = dvbfe_fec(channel.CoderateH());
+     Frontend.delsys.dvbh.code_rate_LP = dvbfe_fec(channel.CoderateL());
+     Frontend.delsys.dvbh.constellation = dvbfe_modulation(channel.Modulation());
+     Frontend.delsys.dvbh.transmission_mode = dvbfe_transmission_mode(channel.Transmission());
+     Frontend.delsys.dvbh.guard_interval = dvbfe_guard_interval(channel.Guard());
+     Frontend.delsys.dvbh.hierarchy = dvbfe_hierarchy(channel.Hierarchy());
+
+//     Frontend.delsys.dvbh.alpha = 0;       //XXX
+//     Frontend.delsys.dvbh.interleaver = 0; //XXX
+//     Frontend.delsys.dvbh.mpefec = 0;      //XXX
+//     Frontend.delsys.dvbh.timeslicing = 0; //XXX
+//     Frontend.delsys.dvbh.priority = 0;    //XXX
+     }
+  else if (frontendType & DVBFE_DELSYS_DSS) {  // DDS
+     Frontend.delivery = DVBFE_DELSYS_DSS;
+     Frontend.delsys.dss.modulation = DVBFE_MOD_QPSK; //XXX
+     Frontend.delsys.dss.symbol_rate = channel.Srate() * 1000UL;
+     Frontend.delsys.dss.fec = dvbfe_fec(channel.CoderateH());
+     }
+  else if (frontendType & DVBFE_DELSYS_ATSC) { // ATCS
+     Frontend.delivery = DVBFE_DELSYS_ATSC;
+     Frontend.delsys.atsc.modulation = DVBFE_MOD_QPSK; //XXX
+     }
+*/
+  else {
+     esyslog("ERROR: attempt to set channel with unknown DVB frontend type");
+     return false;
+     }
+  if (ioctl(fd_frontend, DVBFE_SET_PARAMS, &Frontend) < 0) {
      esyslog("ERROR: frontend %d: %m", cardIndex);
      return false;
      }
@@ -355,7 +406,7 @@  cDvbDevice::cDvbDevice(int n)
 {
   ciAdapter = NULL;
   dvbTuner = NULL;
-  frontendType = fe_type_t(-1); // don't know how else to initialize this - there is no FE_UNKNOWN
+  frontendType = DVBFE_DELSYS_DUMMY;
   spuDecoder = NULL;
   digitalAudio = false;
   playMode = pmNone;
@@ -417,11 +468,8 @@  cDvbDevice::cDvbDevice(int n)
   // We only check the devices that must be present - the others will be checked before accessing them://XXX
 
   if (fd_frontend >= 0) {
-     dvb_frontend_info feinfo;
-     if (ioctl(fd_frontend, FE_GET_INFO, &feinfo) >= 0) {
-        frontendType = feinfo.type;
+     if (ioctl(fd_frontend, DVBFE_GET_DELSYS, &frontendType) >= 0)
         dvbTuner = new cDvbTuner(fd_frontend, CardIndex(), frontendType);
-        }
      else
         LOG_ERROR;
      }
@@ -743,9 +791,9 @@  bool cDvbDevice::ProvidesSource(int Sour
 {
   int type = Source & cSource::st_Mask;
   return type == cSource::stNone
-      || type == cSource::stCable && frontendType == FE_QAM
-      || type == cSource::stSat   && frontendType == FE_QPSK
-      || type == cSource::stTerr  && frontendType == FE_OFDM;
+      || type == cSource::stCable && (frontendType & DVBFE_DELSYS_DVBC)
+      || type == cSource::stSat   && (frontendType & (DVBFE_DELSYS_DVBS | DVBFE_DELSYS_DVBS2))
+      || type == cSource::stTerr  && (frontendType & DVBFE_DELSYS_DVBT);
 }
 
 bool cDvbDevice::ProvidesTransponder(const cChannel *Channel) const
@@ -763,7 +811,7 @@  bool cDvbDevice::ProvidesChannel(const c
      result = hasPriority;
      if (Priority >= 0 && Receiving(true)) {
         if (dvbTuner->IsTunedTo(Channel)) {
-           if (Channel->Vpid() && !HasPid(Channel->Vpid()) || Channel->Apid(0) && !HasPid(Channel->Apid(0))) {
+           if (Channel->Vpid() && !HasPid(VPID_FROM_ANY(Channel->Vpid())) || Channel->Apid(0) && !HasPid(Channel->Apid(0))) {
 #ifdef DO_MULTIPLE_RECORDINGS
               if (CamSlot() && Channel->Ca() >= CA_ENCRYPTED_MIN) {
                  if (CamSlot()->CanDecrypt(Channel))
@@ -799,7 +847,7 @@  bool cDvbDevice::IsTunedToTransponder(co
 bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
 {
   int apid = Channel->Apid(0);
-  int vpid = Channel->Vpid();
+  int vpid = VPID_FROM_ANY(Channel->Vpid());
   int dpid = Channel->Dpid(0);
 
   bool DoTune = !dvbTuner->IsTunedTo(Channel);
@@ -860,7 +908,7 @@  bool cDvbDevice::SetChannelDevice(const 
      CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true));
      }
   else if (StartTransferMode)
-     cControl::Launch(new cTransferControl(this, Channel->GetChannelID(), vpid, Channel->Apids(), Channel->Dpids(), Channel->Spids()));
+     cControl::Launch(new cTransferControl(this, Channel->GetChannelID(), Channel->Vpid(), Channel->Apids(), Channel->Dpids(), Channel->Spids()));
 
   return true;
 }
diff -Nup ../vdr-1.5.10-orig/dvbdevice.h ./dvbdevice.h
--- ../vdr-1.5.10-orig/dvbdevice.h	2007-10-14 15:01:25.000000000 +0200
+++ ./dvbdevice.h	2007-10-14 17:22:27.000000000 +0200
@@ -35,7 +35,7 @@  public:
          ///< Must be called before accessing any DVB functions.
          ///< \return True if any devices are available.
 private:
-  fe_type_t frontendType;
+  dvbfe_delsys frontendType;
   int fd_osd, fd_audio, fd_video, fd_dvr, fd_stc, fd_ca;
 protected:
   virtual void MakePrimaryDevice(bool On);
diff -Nup ../vdr-1.5.10-orig/dvbplayer.c ./dvbplayer.c
--- ../vdr-1.5.10-orig/dvbplayer.c	2007-10-13 14:20:58.000000000 +0200
+++ ./dvbplayer.c	2007-10-14 17:22:27.000000000 +0200
@@ -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;
@@ -673,7 +676,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)
@@ -720,7 +723,8 @@  void cDvbPlayer::Goto(int Index, bool St
               b[r++] = 0x00;
               b[r++] = 0x00;
               b[r++] = 0x01;
-              b[r++] = 0xB7;
+              b[r] = (cRemux::IsFrameH264(b, r) ? 10 : 0xB7);
+              r++;
               }
            DeviceStillPicture(b, r);
            }
@@ -840,3 +844,10 @@  void cDvbPlayerControl::Goto(int Positio
   if (player)
      player->Goto(Position, Still);
 }
+
+int cDvbPlayerControl::GetFramesPerSec()
+{
+  if (player)
+     return player->GetFramesPerSec();
+  return FRAMESPERSEC;
+}
diff -Nup ../vdr-1.5.10-orig/dvbplayer.h ./dvbplayer.h
--- ../vdr-1.5.10-orig/dvbplayer.h	2002-06-23 12:13:51.000000000 +0200
+++ ./dvbplayer.h	2007-08-28 22:25:08.000000000 +0200
@@ -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
diff -Nup ../vdr-1.5.10-orig/h264parser.c ./h264parser.c
--- ../vdr-1.5.10-orig/h264parser.c	1970-01-01 01:00:00.000000000 +0100
+++ ./h264parser.c	2007-08-28 23:28:50.000000000 +0200
@@ -0,0 +1,461 @@ 
+/*
+ * h264parser.c: a minimalistic H.264 video stream parser
+ *
+ * See the main source file 'vdr.c' for copyright information and
+ * how to reach the author.
+ *
+ * The code was originally written by Reinhard Nissl <rnissl@gmx.de>,
+ * and adapted to the VDR coding style by Klaus.Schmidinger@cadsoft.de.
+ */
+
+#include "tools.h"
+#include "h264parser.h"
+
+namespace H264
+{
+  // --- cContext ------------------------------------------------------------
+
+  int cContext::GetFramesPerSec(void) const
+  {
+    const cSequenceParameterSet *SPS = ActiveSPS();
+    const cSliceHeader *SH = CurrentSlice();
+    if (!SH || !SPS->timing_info_present_flag || !SPS->time_scale || !SPS->num_units_in_tick)
+       return -1;
+    uint32_t DeltaTfiDivisor;
+    if (SPS->pic_struct_present_flag) {
+       if (!SPS->pic_timing_sei.Defined())
+          return -1;
+       switch (SPS->pic_timing_sei.pic_struct) {
+         case 1:
+         case 2:
+              DeltaTfiDivisor = 1;
+              break;
+         case 0:
+         case 3:
+         case 4:
+              DeltaTfiDivisor = 2;
+              break;
+         case 5:
+         case 6:
+              DeltaTfiDivisor = 3;
+              break;
+         case 7:
+              DeltaTfiDivisor = 4;
+              break;
+         case 8:
+              DeltaTfiDivisor = 6;
+              break;
+         default:
+              return -1;
+         }
+       }
+    else if (!SH->field_pic_flag)
+       DeltaTfiDivisor = 2;
+    else
+       DeltaTfiDivisor = 1;
+
+    double FPS = (double)SPS->time_scale / SPS->num_units_in_tick / DeltaTfiDivisor / (SH->field_pic_flag ? 2 : 1);
+    int FramesPerSec = (int)FPS;
+    if ((FPS - FramesPerSec) >= 0.5)
+       FramesPerSec++;
+    return FramesPerSec;
+  }
+
+  // --- cSimpleBuffer -------------------------------------------------------
+
+  cSimpleBuffer::cSimpleBuffer(int Size)
+  {
+    size = Size;
+    data = new uchar[size];
+    avail = 0;
+    gotten = 0;
+  }
+
+  cSimpleBuffer::~cSimpleBuffer()
+  {
+    delete data;
+  }
+
+  int cSimpleBuffer::Put(const uchar *Data, int Count)
+  {
+    if (Count < 0) {
+       if (avail + Count < 0)
+          Count = 0 - avail;
+       if (avail + Count < gotten)
+          Count = gotten - avail;
+       avail += Count;
+       return Count;
+       }
+    if (avail + Count > size)
+       Count = size - avail;
+    memcpy(data + avail, Data, Count);
+    avail += Count;
+    return Count;
+  }
+
+  uchar *cSimpleBuffer::Get(int &Count)
+  {
+    Count = gotten = avail;
+    return data;
+  }
+
+  void cSimpleBuffer::Del(int Count)
+  {
+    if (Count < 0)
+       return;
+    if (Count > gotten) {
+       esyslog("ERROR: invalid Count in H264::cSimpleBuffer::Del: %d (limited to %d)", Count, gotten);
+       Count = gotten;
+       }
+    if (Count < avail)
+       memmove(data, data + Count, avail - Count);
+    avail -= Count;
+    gotten = 0;
+  }
+
+  void cSimpleBuffer::Clear(void)
+  {
+    avail = gotten = 0;
+  }
+
+  // --- cParser -------------------------------------------------------------
+
+  cParser::cParser(bool OmitPicTiming)
+    : nalUnitDataBuffer(1000)
+  {
+    // the above buffer size of 1000 bytes wont hold a complete NAL unit but
+    // should be sufficient for the relevant part used for parsing.
+    omitPicTiming = OmitPicTiming; // only necessary to determine frames per second
+    Reset();
+  }
+
+  void cParser::Reset(void)
+  {
+    context = cContext();
+    nalUnitDataBuffer.Clear();
+    syncing = true;
+  }
+
+  void cParser::ParseSequenceParameterSet(uint8_t *Data, int Count)
+  {
+    cSequenceParameterSet SPS;
+
+    cBitReader br(Data + 1, Count - 1);
+    uint32_t profile_idc = br.u(8);
+    /* uint32_t constraint_set0_flag = */ br.u(1);
+    /* uint32_t constraint_set1_flag = */ br.u(1);
+    /* uint32_t constraint_set2_flag = */ br.u(1);
+    /* uint32_t constraint_set3_flag = */ br.u(1);
+    /* uint32_t reserved_zero_4bits = */ br.u(4);
+    /* uint32_t level_idc = */ br.u(8);
+    SPS.seq_parameter_set_id = br.ue();
+    if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 144) {
+       uint32_t chroma_format_idc = br.ue();
+       if (chroma_format_idc == 3) {
+          /* uint32_t residual_colour_transform_flag = */ br.u(1);
+          }
+       /* uint32_t bit_depth_luma_minus8 = */ br.ue();
+       /* uint32_t bit_depth_chroma_minus8 = */ br.ue();
+       /* uint32_t qpprime_y_zero_transform_bypass_flag = */ br.u(1);
+       uint32_t seq_scaling_matrix_present_flag = br.u(1);
+       if (seq_scaling_matrix_present_flag) {
+          for (int i = 0; i < 8; i++) {
+              uint32_t seq_scaling_list_present_flag = br.u(1);
+              if (seq_scaling_list_present_flag) {
+                 int sizeOfScalingList = (i < 6) ? 16 : 64;
+                 int lastScale = 8;
+                 int nextScale = 8;
+                 for (int j = 0; j < sizeOfScalingList; j++) {
+                     if (nextScale != 0) {
+                        int32_t delta_scale = br.se();
+                        nextScale = (lastScale + delta_scale + 256) % 256;
+                        }
+                     lastScale = (nextScale == 0) ? lastScale : nextScale;
+                     }
+                 }
+              }
+          }
+       }
+    SPS.log2_max_frame_num_minus4(br.ue());
+    SPS.pic_order_cnt_type = br.ue();
+    if (SPS.pic_order_cnt_type == 0)
+       SPS.log2_max_pic_order_cnt_lsb_minus4(br.ue());
+    else if (SPS.pic_order_cnt_type == 1) {
+       SPS.delta_pic_order_always_zero_flag = br.u(1);
+       /* int32_t offset_for_non_ref_pic = */ br.se();
+       /* int32_t offset_for_top_to_bottom_field = */ br.se();
+       uint32_t num_ref_frames_in_pic_order_cnt_cycle = br.ue();
+       for (uint32_t i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++) {
+           /* int32_t offset_for_ref_frame = */ br.se();
+           }
+       }
+    /* uint32_t num_ref_frames = */ br.ue();
+    /* uint32_t gaps_in_frame_num_value_allowed_flag = */ br.u(1);
+    /* uint32_t pic_width_in_mbs_minus1 = */ br.ue();
+    /* uint32_t pic_height_in_map_units_minus1 = */ br.ue();
+    SPS.frame_mbs_only_flag = br.u(1);
+
+    if (!omitPicTiming) {
+       if (!SPS.frame_mbs_only_flag) {
+          /* uint32_t mb_adaptive_frame_field_flag = */ br.u(1);
+          }
+       /* uint32_t direct_8x8_inference_flag = */ br.u(1);
+       uint32_t frame_cropping_flag = br.u(1);
+       if (frame_cropping_flag) {
+          /* uint32_t frame_crop_left_offset = */ br.ue();
+          /* uint32_t frame_crop_right_offset = */ br.ue();
+          /* uint32_t frame_crop_top_offset = */ br.ue();
+          /* uint32_t frame_crop_bottom_offset = */ br.ue();
+          }
+       uint32_t vui_parameters_present_flag = br.u(1);
+       if (vui_parameters_present_flag) {
+          uint32_t aspect_ratio_info_present_flag = br.u(1);
+          if (aspect_ratio_info_present_flag) {
+             uint32_t aspect_ratio_idc = br.u(8);
+             const uint32_t Extended_SAR = 255;
+             if (aspect_ratio_idc == Extended_SAR) {
+                /* uint32_t sar_width = */ br.u(16);
+                /* uint32_t sar_height = */ br.u(16);
+                }
+             }
+          uint32_t overscan_info_present_flag = br.u(1);
+          if (overscan_info_present_flag) {
+             /* uint32_t overscan_appropriate_flag = */ br.u(1);
+             }
+          uint32_t video_signal_type_present_flag = br.u(1);
+          if (video_signal_type_present_flag) {
+             /* uint32_t video_format = */ br.u(3);
+             /* uint32_t video_full_range_flag = */ br.u(1);
+             uint32_t colour_description_present_flag = br.u(1);
+             if (colour_description_present_flag) {
+                /* uint32_t colour_primaries = */ br.u(8);
+                /* uint32_t transfer_characteristics = */ br.u(8);
+                /* uint32_t matrix_coefficients = */ br.u(8);
+                }
+             }
+          uint32_t chroma_loc_info_present_flag = br.u(1);
+          if (chroma_loc_info_present_flag) {
+             /* uint32_t chroma_sample_loc_type_top_field = */ br.ue();
+             /* uint32_t chroma_sample_loc_type_bottom_field = */ br.ue();
+             }
+          SPS.timing_info_present_flag = br.u(1);
+          if (SPS.timing_info_present_flag) {
+             SPS.num_units_in_tick = br.u(32);
+             SPS.time_scale = br.u(32);
+             SPS.fixed_frame_rate_flag = br.u(1);
+             }
+          SPS.nal_hrd_parameters_present_flag = br.u(1);
+          if (SPS.nal_hrd_parameters_present_flag)
+             hrd_parameters(SPS, br);
+          SPS.vcl_hrd_parameters_present_flag = br.u(1);
+          if (SPS.vcl_hrd_parameters_present_flag)
+             hrd_parameters(SPS, br);
+          if (SPS.nal_hrd_parameters_present_flag || SPS.vcl_hrd_parameters_present_flag) {
+             /* uint32_t low_delay_hrd_flag = */ br.u(1);
+             }
+          SPS.pic_struct_present_flag = br.u(1);
+          }
+       }
+
+    context.Define(SPS);
+  }
+
+  void cParser::hrd_parameters(cSequenceParameterSet &SPS, cBitReader &br)
+  {
+    uint32_t cpb_cnt_minus1 = br.ue();
+    /* uint32_t bit_rate_scale = */ br.u(4);
+    /* uint32_t cpb_size_scale = */ br.u(4);
+    for (uint32_t i = 0; i <= cpb_cnt_minus1; i++) {
+        /* uint32_t bit_rate_value_minus1 = */ br.ue();
+        /* uint32_t cpb_size_value_minus1 = */ br.ue();
+        /* uint32_t cbr_flag = */ br.u(1);
+        }
+    /* uint32_t initial_cpb_removal_delay_length_minus1 = */ br.u(5);
+    SPS.cpb_removal_delay_length_minus1(br.u(5));
+    SPS.dpb_output_delay_length_minus1(br.u(5));
+    /* uint32_t time_offset_length = */ br.u(5);
+  }
+
+  void cParser::ParsePictureParameterSet(uint8_t *Data, int Count)
+  {
+    cPictureParameterSet PPS;
+
+    cBitReader br(Data + 1, Count - 1);
+    PPS.pic_parameter_set_id = br.ue();
+    PPS.seq_parameter_set_id = br.ue();
+    /* uint32_t entropy_coding_mode_flag = */ br.u(1);
+    PPS.pic_order_present_flag = br.u(1);
+
+    context.Define(PPS);
+  }
+
+  void cParser::ParseSlice(uint8_t *Data, int Count)
+  {
+    cSliceHeader SH;
+
+    cBitReader br(Data + 1, Count - 1);
+    SH.nal_ref_idc(Data[0] >> 5);
+    SH.nal_unit_type(Data[0] & 0x1F);
+    /* uint32_t first_mb_in_slice = */ br.ue();
+    SH.slice_type = br.ue();
+    SH.pic_parameter_set_id = br.ue();
+
+    context.ActivatePPS(SH.pic_parameter_set_id);
+    const cSequenceParameterSet *SPS = context.ActiveSPS();
+
+    SH.frame_num = br.u(SPS->log2_max_frame_num());
+    if (!SPS->frame_mbs_only_flag) {
+       SH.field_pic_flag = br.u(1);
+       if (SH.field_pic_flag)
+          SH.bottom_field_flag = br.u(1);
+       }
+    if (SH.nal_unit_type() == 5)
+       SH.idr_pic_id = br.ue();
+    if (SPS->pic_order_cnt_type == 0) {
+       SH.pic_order_cnt_lsb = br.u(SPS->log2_max_pic_order_cnt_lsb());
+       const cPictureParameterSet *PPS = context.ActivePPS();
+       if (PPS->pic_order_present_flag && !SH.field_pic_flag)
+          SH.delta_pic_order_cnt_bottom = br.se();
+       }
+    if (SPS->pic_order_cnt_type == 1 && !SPS->delta_pic_order_always_zero_flag) {
+       SH.delta_pic_order_cnt[0] = br.se();
+       const cPictureParameterSet *PPS = context.ActivePPS();
+       if (PPS->pic_order_present_flag && !SH.field_pic_flag)
+          SH.delta_pic_order_cnt[1] = br.se();
+       }
+
+    context.Define(SH);
+  }
+
+  void cParser::ParseSEI(uint8_t *Data, int Count)
+  {
+    // currently only used to determine frames per second
+    if (omitPicTiming)
+       return;
+    cBitReader br(Data + 1, Count - 1);
+    do
+      sei_message(br);
+    while (br.GetBytesAvail());
+  }
+
+  void cParser::sei_message(cBitReader &br)
+  {
+    uint32_t payloadType = 0;
+    while (1) {
+          uint32_t last_payload_type_byte = br.u(8);
+          payloadType += last_payload_type_byte;
+          if (last_payload_type_byte != 0xFF)
+             break;
+          }
+    uint32_t payloadSize = 0;
+    while (1) {
+          uint32_t last_payload_size_byte = br.u(8);
+          payloadSize += last_payload_size_byte;
+          if (last_payload_size_byte != 0xFF)
+             break;
+          }
+    sei_payload(payloadType, payloadSize, br);
+  }
+
+  void cParser::sei_payload(uint32_t payloadType, uint32_t payloadSize, cBitReader &br)
+  {
+    const cBitReader::cBookMark BookMark = br.BookMark();
+    switch (payloadType) {
+      case 0:
+           buffering_period(payloadSize, br);
+           break;
+      case 1:
+           pic_timing(payloadSize, br);
+           break;
+      }
+    // instead of dealing with trailing bits in each message
+    // go back to start of message and skip it completely
+    br.BookMark(BookMark);
+    reserved_sei_message(payloadSize, br);
+  }
+
+  void cParser::buffering_period(uint32_t payloadSize, cBitReader &br)
+  {
+    uint32_t seq_parameter_set_id = br.ue();
+
+    context.ActivateSPS(seq_parameter_set_id);
+  }
+
+  void cParser::pic_timing(uint32_t payloadSize, cBitReader &br)
+  {
+    cPictureTiming PT;
+
+    const cSequenceParameterSet *SPS = context.ActiveSPS();
+    if (!SPS)
+       return;
+    uint32_t CpbDpbDelaysPresentFlag = SPS->nal_hrd_parameters_present_flag || SPS->vcl_hrd_parameters_present_flag;
+    if (CpbDpbDelaysPresentFlag) {
+       /* uint32_t cpb_removal_delay = */ br.u(SPS->cpb_removal_delay_length());
+       /* uint32_t dpb_output_delay = */ br.u(SPS->dpb_output_delay_length());
+       }
+    if (SPS->pic_struct_present_flag) {
+       PT.pic_struct = br.u(4);
+       }
+
+    context.Define(PT);
+  }
+
+  void cParser::reserved_sei_message(uint32_t payloadSize, cBitReader &br)
+  {
+    for (uint32_t i = 0; i < payloadSize; i++) {
+        /* uint32_t reserved_sei_message_payload_byte = */ br.u(8);
+        }
+  }
+
+  void cParser::PutNalUnitData(const uchar *Data, int Count)
+  {
+    int n = nalUnitDataBuffer.Put(Data, Count);
+    // typically less than a complete NAL unit are needed for parsing the
+    // relevant data, so simply ignore the overflow condition.
+    if (false && n != Count)
+       esyslog("ERROR: H264::cParser::PutNalUnitData(): NAL unit data buffer overflow");
+  }
+
+  void cParser::Process()
+  {
+    // nalUnitDataBuffer contains the head of the current NAL unit -- let's parse it 
+    int Count = 0;
+    uchar *Data = nalUnitDataBuffer.Get(Count);
+    if (Data && Count >= 4) {
+       if (Data[0] == 0x00 && Data[1] == 0x00 && Data[2] == 0x01) {
+          int nal_unit_type = Data[3] & 0x1F;
+          try {
+              switch (nal_unit_type) {
+                case 1: // coded slice of a non-IDR picture
+                case 2: // coded slice data partition A
+                case 5: // coded slice of an IDR picture
+                     ParseSlice(Data + 3, Count - 3);
+                     break;
+                case 6: // supplemental enhancement information (SEI)
+                     ParseSEI(Data + 3, Count - 3);
+                     break;
+                case 7: // sequence parameter set
+                     syncing = false; // from now on, we should get reliable results
+                     ParseSequenceParameterSet(Data + 3, Count - 3);
+                     break;
+                case 8: // picture parameter set
+                     ParsePictureParameterSet(Data + 3, Count - 3);
+                     break;
+                }
+              }
+          catch (cException *e) {
+              if (!syncing) // suppress typical error messages while syncing
+                 esyslog(e->Message());
+              delete e;
+              }
+          }
+       else if (!syncing)
+          esyslog("ERROR: H264::cParser::Process(): NAL unit data buffer content is invalid");
+       }
+    else if (!syncing)
+       esyslog("ERROR: H264::cParser::Process(): NAL unit data buffer content is too short");
+    // reset the buffer for the next NAL unit
+    nalUnitDataBuffer.Clear();
+  }
+}
+
diff -Nup ../vdr-1.5.10-orig/h264parser.h ./h264parser.h
--- ../vdr-1.5.10-orig/h264parser.h	1970-01-01 01:00:00.000000000 +0100
+++ ./h264parser.h	2007-08-28 23:18:31.000000000 +0200
@@ -0,0 +1,397 @@ 
+/*
+ * h264parser.h: a minimalistic H.264 video stream parser
+ *
+ * See the main source file 'vdr.c' for copyright information and
+ * how to reach the author.
+ */
+
+#ifndef __H264PARSER_H
+#define __H264PARSER_H
+
+namespace H264
+{
+  // --- cException ----------------------------------------------------------
+
+  class cException {
+  private:
+    cString message;
+  public:
+    cException(const cString &Message) { message = Message; }
+    const cString &Message(void) const { return message; }
+  };
+
+  // --- cBitReader ----------------------------------------------------------
+
+  class cBitReader {
+  public:
+    class cBookMark {
+    private:
+      uint8_t *data;
+      int count;
+      uint32_t bits;
+      uint32_t bitsAvail;
+      int countZeros;
+      cBookMark(void) {}
+      friend class cBitReader;
+    };
+  private:
+    cBookMark bm;
+    uint8_t NextByte(void);
+    uint32_t ReadBits(uint32_t n);
+  public:
+    cBitReader(uint8_t *Data, int Count);
+    uint32_t u(uint32_t n) { return ReadBits(n); } // read n bits as unsigned number
+    uint32_t ue(void); // read Exp-Golomb coded unsigned number
+    int32_t se(void); // read Exp-Golomb coded signed number
+    uint32_t GetBitsAvail(void) { return (bm.bitsAvail & 0x07); }
+    bool GetBytesAvail(void) { return (bm.count > 0); }
+    const cBookMark BookMark(void) const { return bm; }
+    void BookMark(const cBookMark &b) { bm = b; }
+  };
+
+  inline cBitReader::cBitReader(unsigned char *Data, int Count)
+  {
+    bm.data = Data;
+    bm.count = Count;
+    bm.bitsAvail = 0;
+    bm.countZeros = 0;
+  }
+
+  inline uint8_t cBitReader::NextByte(void)
+  {
+    if (bm.count < 1) // there is no more data left in this NAL unit
+       throw new cException("ERROR: H264::cBitReader::NextByte(): premature end of data");
+    // detect 00 00 00, 00 00 01 and 00 00 03 and handle them
+    if (*bm.data == 0x00) {
+       if (bm.countZeros >= 3) // 00 00 00: the current NAL unit should have been terminated already before this sequence
+          throw new cException("ERROR: H264::cBitReader::NextByte(): premature end of data");
+       // increase the zero counter as we have a zero byte
+       bm.countZeros++;
+       }
+    else {
+       if (bm.countZeros >= 2) {
+          if (*bm.data == 0x01) // 00 00 01: the current NAL unit should have been terminated already before this sequence
+             throw new cException("ERROR: H264::cBitReader::NextByte(): premature end of data");
+          if (*bm.data == 0x03) {
+             // 00 00 03 xx: the emulation prevention byte 03 needs to be removed and xx must be returned
+             if (bm.count < 2)
+                throw new cException("ERROR: H264::cBitReader::NextByte(): premature end of data");
+             // drop 03 and xx will be returned below
+             bm.count--;
+             bm.data++;
+             }
+          }
+       // reset the zero counter as we had a non zero byte
+       bm.countZeros = 0;
+       }
+    bm.count--;
+    return *bm.data++;
+  }
+
+  inline uint32_t cBitReader::ReadBits(uint32_t n)
+  {
+    // fill the "shift register" bits with sufficient data
+    while (n > bm.bitsAvail) {
+          bm.bits <<= 8;
+          bm.bits |= NextByte();
+          bm.bitsAvail += 8;
+          if (bm.bitsAvail > 24) { // a further turn will overflow bitbuffer
+             if (n <= bm.bitsAvail)
+                break; // service non overflowing request
+             if (n <= 32) // split overflowing reads into concatenated reads 
+                return (ReadBits(16) << 16) | ReadBits(n - 16);
+             // cannot read more than 32 bits at once
+             throw new cException("ERROR: H264::cBitReader::ReadBits(): bitbuffer overflow");
+             }
+          }
+    // return n most significant bits
+    bm.bitsAvail -= n;
+    return (bm.bits >> bm.bitsAvail) & (((uint32_t)1 << n) - 1);
+  }
+
+  inline uint32_t cBitReader::ue(void)
+  {
+    // read and decode an Exp-Golomb coded unsigned number
+    //
+    // bitstring             resulting number
+    //       1               0
+    //     0 1 x             1 ... 2
+    //   0 0 1 x y           3 ... 6
+    // 0 0 0 1 x y z         7 ... 14
+    // ...
+    int LeadingZeroBits = 0;
+    while (ReadBits(1) == 0)
+          LeadingZeroBits++;
+    if (LeadingZeroBits == 0)
+       return 0;
+    if (LeadingZeroBits >= 32)
+       throw new cException("ERROR: H264::cBitReader::ue(): overflow");
+    return ((uint32_t)1 << LeadingZeroBits) - 1 + ReadBits(LeadingZeroBits);
+  }
+
+  inline int32_t cBitReader::se(void)
+  {
+    // read and decode an Exp-Golomb coded signed number
+    //
+    // unsigned value       resulting signed value
+    // 0                     0
+    // 1                    +1
+    // 2                    -1
+    // 3                    +2
+    // 4                    -2
+    // ...
+    uint32_t r = ue();
+    if (r > 0xFFFFFFFE)
+       throw new cException("ERROR: H264::cBitReader::se(): overflow");
+    return (1 - 2 * (r & 1)) * ((r + 1) / 2);
+  }
+
+  // --- cPictureTiming ------------------------------------------------------
+
+  class cPictureTiming {
+  private:
+    friend class cContext;
+    bool defined;
+  public:
+    cPictureTiming(void) { memset(this, 0, sizeof (*this)); }
+    bool Defined(void) const { return defined; }
+    uint32_t pic_struct;
+  };
+
+  // --- cSequenceParameterSet -----------------------------------------------
+
+  class cSequenceParameterSet {
+  private:
+    friend class cContext;
+    bool defined;
+    uint32_t log2MaxFrameNum;
+    uint32_t log2MaxPicOrderCntLsb;
+    uint32_t cpbRemovalDelayLength;
+    uint32_t dpbOutputDelayLength;
+  public:
+    cSequenceParameterSet(void);
+    bool Defined(void) { return defined; }
+    void log2_max_frame_num_minus4(uint32_t Value) { log2MaxFrameNum = Value + 4; }
+    uint32_t log2_max_frame_num_minus4(void) const { return log2MaxFrameNum - 4; }
+    uint32_t log2_max_frame_num(void) const { return log2MaxFrameNum; }
+    void log2_max_pic_order_cnt_lsb_minus4(uint32_t Value) { log2MaxPicOrderCntLsb = Value + 4; }
+    uint32_t log2_max_pic_order_cnt_lsb_minus4(void) const { return log2MaxPicOrderCntLsb - 4; }
+    uint32_t log2_max_pic_order_cnt_lsb(void) const { return log2MaxPicOrderCntLsb; }
+    void cpb_removal_delay_length_minus1(uint32_t Value) { cpbRemovalDelayLength = Value + 1; }
+    uint32_t cpb_removal_delay_length_minus1(void) const { return cpbRemovalDelayLength - 1; }
+    uint32_t cpb_removal_delay_length(void) const { return cpbRemovalDelayLength; }
+    void dpb_output_delay_length_minus1(uint32_t Value) { dpbOutputDelayLength = Value + 1; }
+    uint32_t dpb_output_delay_length_minus1(void) const { return dpbOutputDelayLength - 1; }
+    uint32_t dpb_output_delay_length(void) const { return dpbOutputDelayLength; }
+    uint32_t seq_parameter_set_id;
+    uint32_t pic_order_cnt_type;
+    uint32_t delta_pic_order_always_zero_flag;
+    uint32_t frame_mbs_only_flag;
+    uint32_t timing_info_present_flag;
+    uint32_t num_units_in_tick;
+    uint32_t time_scale;
+    uint32_t fixed_frame_rate_flag;
+    uint32_t nal_hrd_parameters_present_flag;
+    uint32_t vcl_hrd_parameters_present_flag;
+    uint32_t pic_struct_present_flag;
+    cPictureTiming pic_timing_sei;
+  };
+
+  inline cSequenceParameterSet::cSequenceParameterSet(void)
+  {
+    memset(this, 0, sizeof (*this));
+    log2_max_frame_num_minus4(0);
+    log2_max_pic_order_cnt_lsb_minus4(0);
+    cpb_removal_delay_length_minus1(23);
+    dpb_output_delay_length_minus1(23);
+  }
+
+  // --- cPictureParameterSet ------------------------------------------------
+
+  class cPictureParameterSet {
+  private:
+    friend class cContext;
+    bool defined;
+  public:
+    cPictureParameterSet(void) { memset(this, 0, sizeof (*this)); }
+    bool Defined(void) { return defined; }
+    uint32_t pic_parameter_set_id;
+    uint32_t seq_parameter_set_id;
+    uint32_t pic_order_present_flag;
+  };
+
+  // --- cSliceHeader --------------------------------------------------------
+
+  class cSliceHeader {
+  private:
+    friend class cContext;
+    bool defined;
+    bool isFirstSliceOfCurrentAccessUnit;
+    uint32_t picOrderCntType;
+    uint32_t nalRefIdc;
+    uint32_t nalUnitType;
+  public:
+    cSliceHeader(void) { memset(this, 0, sizeof (*this)); }
+    bool Defined(void) const { return defined; }
+    bool IsFirstSliceOfCurrentAccessUnit(void) const { return isFirstSliceOfCurrentAccessUnit; }
+    void nal_ref_idc(uint32_t Value) { nalRefIdc = Value; }
+    uint32_t nal_ref_idc(void) const { return nalRefIdc; }
+    void nal_unit_type(uint32_t Value) { nalUnitType = Value; }
+    uint32_t nal_unit_type(void) const { return nalUnitType; }
+    uint32_t slice_type;
+    uint32_t pic_parameter_set_id;
+    uint32_t frame_num;
+    uint32_t field_pic_flag;
+    uint32_t bottom_field_flag;
+    uint32_t idr_pic_id;
+    uint32_t pic_order_cnt_lsb;
+    int32_t delta_pic_order_cnt_bottom;
+    int32_t delta_pic_order_cnt[2];
+    enum eAccessUnitType {
+      Frame = 0,
+      TopField,
+      BottomField
+      };
+    eAccessUnitType GetAccessUnitType() const { return (eAccessUnitType)(field_pic_flag + bottom_field_flag); }
+  };
+
+  // --- cContext ------------------------------------------------------------
+
+  class cContext {
+  private:
+    cSequenceParameterSet spsStore[32];
+    cPictureParameterSet ppsStore[256];
+    cSequenceParameterSet *sps; // active Sequence Parameter Set
+    cPictureParameterSet *pps; // active Picture Parameter Set
+    cSliceHeader sh;
+  public:
+    cContext(void) { sps = 0; pps = 0; }
+    void Define(cSequenceParameterSet &SPS);
+    void Define(cPictureParameterSet &PPS);
+    void Define(cSliceHeader &SH);
+    void Define(cPictureTiming &PT);
+    void ActivateSPS(uint32_t ID);
+    void ActivatePPS(uint32_t ID);
+    const cSequenceParameterSet *ActiveSPS(void) const { return sps; }
+    const cPictureParameterSet *ActivePPS(void) const { return pps; }
+    const cSliceHeader *CurrentSlice(void) const { return sh.Defined() ? &sh : 0; }
+    int GetFramesPerSec(void) const;
+  };
+
+  inline void cContext::ActivateSPS(uint32_t ID)
+  {
+    if (ID >= (sizeof (spsStore) / sizeof (*spsStore)))
+       throw new cException("ERROR: H264::cContext::ActivateSPS(): id out of range");
+    if (!spsStore[ID].Defined())
+       throw new cException("ERROR: H264::cContext::ActivateSPS(): requested SPS is undefined");
+    sps = &spsStore[ID];
+  }
+
+  inline void cContext::ActivatePPS(uint32_t ID)
+  {
+    if (ID >= (sizeof (ppsStore) / sizeof (*ppsStore)))
+       throw new cException("ERROR: H264::cContext::ActivatePPS(): id out of range");
+    if (!ppsStore[ID].Defined())
+       throw new cException("ERROR: H264::cContext::ActivatePPS(): requested PPS is undefined");
+    pps = &ppsStore[ID];
+    ActivateSPS(pps->seq_parameter_set_id);
+  }
+
+  inline void cContext::Define(cSequenceParameterSet &SPS)
+  {
+    if (SPS.seq_parameter_set_id >= (sizeof (spsStore) / sizeof (*spsStore)))
+       throw new cException("ERROR: H264::cContext::DefineSPS(): id out of range");
+    SPS.defined = true;
+    spsStore[SPS.seq_parameter_set_id] = SPS;
+  }
+
+  inline void cContext::Define(cPictureParameterSet &PPS)
+  {
+    if (PPS.pic_parameter_set_id >= (sizeof (ppsStore) / sizeof (*ppsStore)))
+       throw new cException("ERROR: H264::cContext::DefinePPS(): id out of range");
+    PPS.defined = true;
+    ppsStore[PPS.pic_parameter_set_id] = PPS;
+  }
+
+  inline void cContext::Define(cSliceHeader &SH)
+  {
+    SH.defined = true;
+    SH.picOrderCntType = ActiveSPS()->pic_order_cnt_type;
+
+    // ITU-T Rec. H.264 (03/2005): 7.4.1.2.4
+    SH.isFirstSliceOfCurrentAccessUnit = !sh.Defined()
+      || (sh.frame_num                  != SH.frame_num)
+      || (sh.pic_parameter_set_id       != SH.pic_parameter_set_id)
+      || (sh.field_pic_flag             != SH.field_pic_flag)
+      || (sh.bottom_field_flag          != SH.bottom_field_flag)
+      || (sh.nalRefIdc                  != SH.nalRefIdc
+      && (sh.nalRefIdc == 0             || SH.nalRefIdc == 0))
+      || (sh.picOrderCntType == 0       && SH.picOrderCntType == 0
+      && (sh.pic_order_cnt_lsb          != SH.pic_order_cnt_lsb
+      ||  sh.delta_pic_order_cnt_bottom != SH.delta_pic_order_cnt_bottom))
+      || (sh.picOrderCntType == 1       && SH.picOrderCntType == 1
+      && (sh.delta_pic_order_cnt[0]     != SH.delta_pic_order_cnt[0]
+      ||  sh.delta_pic_order_cnt[1]     != SH.delta_pic_order_cnt[1]))
+      || (sh.nalUnitType                != SH.nalUnitType
+      && (sh.nalUnitType == 5           || SH.nalUnitType == 5))
+      || (sh.nalUnitType == 5           && SH.nalUnitType == 5
+      &&  sh.idr_pic_id                 != SH.idr_pic_id);
+        
+    sh = SH;
+  }
+
+  inline void cContext::Define(cPictureTiming &PT)
+  {
+    PT.defined = true;
+    ((cSequenceParameterSet *)ActiveSPS())->pic_timing_sei = PT;
+  }
+
+  // --- cSimpleBuffer -------------------------------------------------------
+
+  class cSimpleBuffer {
+  private:
+    uchar *data;
+    int size;
+    int avail;
+    int gotten;
+  public:
+    cSimpleBuffer(int Size);
+    ~cSimpleBuffer();
+    int Size(void) { return size; }
+    int Available(void) { return avail; }
+    int Free(void) { return size - avail; }
+    int Put(const uchar *Data, int Count);
+    uchar *Get(int &Count);
+    void Del(int Count);
+    void Clear(void);
+  };
+
+  // --- cParser -------------------------------------------------------------
+
+  class cParser {
+  private:
+    bool syncing;
+    bool omitPicTiming;
+    cContext context;
+    cSimpleBuffer nalUnitDataBuffer;
+    void hrd_parameters(cSequenceParameterSet &SPS, cBitReader &br);
+    void ParseSequenceParameterSet(uint8_t *Data, int Count);
+    void ParsePictureParameterSet(uint8_t *Data, int Count);
+    void ParseSlice(uint8_t *Data, int Count);
+    void reserved_sei_message(uint32_t payloadSize, cBitReader &br);
+    void pic_timing(uint32_t payloadSize, cBitReader &br);
+    void buffering_period(uint32_t payloadSize, cBitReader &br);
+    void sei_payload(uint32_t payloadType, uint32_t payloadSize, cBitReader &br);
+    void sei_message(cBitReader &br);
+    void ParseSEI(uint8_t *Data, int Count);
+  public:
+    cParser(bool OmitPicTiming = true);
+    const cContext &Context(void) const { return context; }
+    void PutNalUnitData(const uchar *Data, int Count);
+    void Reset(void);
+    void Process(void);
+  };
+}
+
+#endif // __H264PARSER_H
+
diff -Nup ../vdr-1.5.10-orig/menu.c ./menu.c
--- ../vdr-1.5.10-orig/menu.c	2007-10-13 12:10:20.000000000 +0200
+++ ./menu.c	2007-10-14 17:27:00.000000000 +0200
@@ -218,6 +218,7 @@  class cMenuEditChannel : public cOsdMenu
 private:
   cChannel *channel;
   cChannel data;
+  int vcodec;
   char name[256];
   void Setup(void);
 public:
@@ -231,6 +232,9 @@  cMenuEditChannel::cMenuEditChannel(cChan
   channel = Channel;
   if (channel) {
      data = *channel;
+     vcodec = data.vpid / VPID_OFFSET_BASE;
+     data.vpid = VPID_FROM_ANY(data.vpid);
+
      if (New) {
         channel = NULL;
         data.nid = 0;
@@ -249,22 +253,28 @@  void cMenuEditChannel::Setup(void)
 
   Clear();
 
+  static const char *VideoCodecValues[] = {
+    tr("MPEG1/2"),
+    tr("H.264")
+    };
+
   // Parameters for all types of sources:
   strn0cpy(name, data.name, sizeof(name));
   Add(new cMenuEditStrItem( tr("Name"),          name, sizeof(name), tr(FileNameChars)));
   Add(new cMenuEditSrcItem( tr("Source"),       &data.source));
   Add(new cMenuEditIntItem( tr("Frequency"),    &data.frequency));
-  Add(new cMenuEditIntItem( tr("Vpid"),         &data.vpid,  0, 0x1FFF));
-  Add(new cMenuEditIntItem( tr("Ppid"),         &data.ppid,  0, 0x1FFF));
+  Add(new cMenuEditIntItem( tr("Vpid"),         &data.vpid,     0, 0x1FFF));
+  Add(new cMenuEditStraItem( tr("Vcodec"),      &vcodec, sizeof(VideoCodecValues) / sizeof(*VideoCodecValues), VideoCodecValues));
+  Add(new cMenuEditIntItem( tr("Ppid"),         &data.ppid,     0, 0x1FFF));
   Add(new cMenuEditIntItem( tr("Apid1"),        &data.apids[0], 0, 0x1FFF));
   Add(new cMenuEditIntItem( tr("Apid2"),        &data.apids[1], 0, 0x1FFF));
   Add(new cMenuEditIntItem( tr("Dpid1"),        &data.dpids[0], 0, 0x1FFF));
   Add(new cMenuEditIntItem( tr("Dpid2"),        &data.dpids[1], 0, 0x1FFF));
   Add(new cMenuEditIntItem( tr("Spid1"),        &data.spids[0], 0, 0x1FFF));
   Add(new cMenuEditIntItem( tr("Spid2"),        &data.spids[1], 0, 0x1FFF));
-  Add(new cMenuEditIntItem( tr("Tpid"),         &data.tpid,  0, 0x1FFF));
+  Add(new cMenuEditIntItem( tr("Tpid"),         &data.tpid,     0, 0x1FFF));
   Add(new cMenuEditCaItem(  tr("CA"),           &data.caids[0]));
-  Add(new cMenuEditIntItem( tr("Sid"),          &data.sid, 1, 0xFFFF));
+  Add(new cMenuEditIntItem( tr("Sid"),          &data.sid,      1, 0xFFFF));
   /* XXX not yet used
   Add(new cMenuEditIntItem( tr("Nid"),          &data.nid, 0));
   Add(new cMenuEditIntItem( tr("Tid"),          &data.tid, 0));
@@ -296,12 +306,14 @@  eOSState cMenuEditChannel::ProcessKey(eK
         if (Channels.HasUniqueChannelID(&data, channel)) {
            data.name = strcpyrealloc(data.name, name);
            if (channel) {
+              data.vpid += vcodec * VPID_OFFSET_BASE; 
               *channel = data;
               isyslog("edited channel %d %s", channel->Number(), *data.ToText());
               state = osBack;
               }
            else {
               channel = new cChannel;
+              data.vpid += vcodec * VPID_OFFSET_BASE; 
               *channel = data;
               Channels.Add(channel);
               Channels.ReNumber();
@@ -4160,7 +4172,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();
         }
@@ -4168,7 +4180,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;
         }
@@ -4201,8 +4213,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) {
@@ -4229,7 +4241,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:
@@ -4350,7 +4362,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();
            }
         }
diff -Nup ../vdr-1.5.10-orig/nit.c ./nit.c
--- ../vdr-1.5.10-orig/nit.c	2007-08-17 16:02:45.000000000 +0200
+++ ./nit.c	2007-08-26 19:23:46.000000000 +0200
@@ -127,8 +127,14 @@  void cNitFilter::Process(u_short Pid, u_
                  int Frequency = Frequencies[0] = BCD2INT(sd->getFrequency()) / 100;
                  static char Polarizations[] = { 'h', 'v', 'l', 'r' };
                  char Polarization = Polarizations[sd->getPolarization()];
-                 static int CodeRates[] = { FEC_NONE, FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_NONE };
+                 static int CodeRates[] = { DVBFE_FEC_NONE, DVBFE_FEC_1_2, DVBFE_FEC_2_3, DVBFE_FEC_3_4, DVBFE_FEC_5_6, DVBFE_FEC_7_8, DVBFE_FEC_8_9, DVBFE_FEC_3_5, DVBFE_FEC_4_5, DVBFE_FEC_9_10, DVBFE_FEC_AUTO, DVBFE_FEC_AUTO, DVBFE_FEC_AUTO, DVBFE_FEC_AUTO, DVBFE_FEC_AUTO, DVBFE_FEC_NONE };
                  int CodeRate = CodeRates[sd->getFecInner()];
+                 static int Modulations[] = { DVBFE_MOD_AUTO, DVBFE_MOD_QPSK, DVBFE_MOD_8PSK, DVBFE_MOD_QAM16 };
+                 int Modulation = Modulations[sd->getModulationType()];
+                 int ModulationSystem = sd->getModulationSystem() ? DVBFE_DELSYS_DVBS2 : DVBFE_DELSYS_DVBS;
+                 static int RollOffs[] = { DVBFE_ROLLOFF_35, DVBFE_ROLLOFF_25, DVBFE_ROLLOFF_20, DVBFE_ROLLOFF_UNKNOWN };
+                 int RollOff = sd->getModulationSystem() ? RollOffs[sd->getRollOff()] : DVBFE_ROLLOFF_UNKNOWN;
+                 //XXX rollOff really necessary???
                  int SymbolRate = BCD2INT(sd->getSymbolRate()) / 10;
                  if (ThisNIT >= 0) {
                     for (int n = 0; n < NumFrequencies; n++) {
@@ -154,7 +160,7 @@  void cNitFilter::Process(u_short Pid, u_
                                   }
                               }
                            if (ISTRANSPONDER(cChannel::Transponder(Frequency, Polarization), Transponder())) // only modify channels if we're actually receiving this transponder
-                              Channel->SetSatTransponderData(Source, Frequency, Polarization, SymbolRate, CodeRate);
+                              Channel->SetSatTransponderData(Source, Frequency, Polarization, SymbolRate, CodeRate, Modulation, ModulationSystem, RollOff);
                            }
                         found = true;
                         }
@@ -162,7 +168,7 @@  void cNitFilter::Process(u_short Pid, u_
                        for (int n = 0; n < NumFrequencies; n++) {
                            cChannel *Channel = new cChannel;
                            Channel->SetId(ts.getOriginalNetworkId(), ts.getTransportStreamId(), 0, 0);
-                           if (Channel->SetSatTransponderData(Source, Frequencies[n], Polarization, SymbolRate, CodeRate))
+                           if (Channel->SetSatTransponderData(Source, Frequencies[n], Polarization, SymbolRate, CodeRate, Modulation, ModulationSystem, RollOff))
                               EITScanner.AddTransponder(Channel);
                            else
                               delete Channel;
@@ -176,9 +182,9 @@  void cNitFilter::Process(u_short Pid, u_
                  int Source = cSource::FromData(cSource::stCable);
                  int Frequency = Frequencies[0] = BCD2INT(sd->getFrequency()) / 10;
                  //XXX FEC_outer???
-                 static int CodeRates[] = { FEC_NONE, FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_NONE };
+                 static int CodeRates[] = { DVBFE_FEC_NONE, DVBFE_FEC_1_2, DVBFE_FEC_2_3, DVBFE_FEC_3_4, DVBFE_FEC_5_6, DVBFE_FEC_7_8, DVBFE_FEC_8_9, DVBFE_FEC_3_5, DVBFE_FEC_4_5, DVBFE_FEC_9_10, DVBFE_FEC_AUTO, DVBFE_FEC_AUTO, DVBFE_FEC_AUTO, DVBFE_FEC_AUTO, DVBFE_FEC_AUTO, DVBFE_FEC_NONE };
                  int CodeRate = CodeRates[sd->getFecInner()];
-                 static int Modulations[] = { QPSK, QAM_16, QAM_32, QAM_64, QAM_128, QAM_256, QAM_AUTO };
+                 static int Modulations[] = { DVBFE_MOD_NONE, DVBFE_MOD_QAM16, DVBFE_MOD_QAM32, DVBFE_MOD_QAM64, DVBFE_MOD_QAM128, DVBFE_MOD_QAM256, QAM_AUTO };
                  int Modulation = Modulations[min(sd->getModulation(), 6)];
                  int SymbolRate = BCD2INT(sd->getSymbolRate()) / 10;
                  if (ThisNIT >= 0) {
@@ -226,19 +232,27 @@  void cNitFilter::Process(u_short Pid, u_
                  SI::TerrestrialDeliverySystemDescriptor *sd = (SI::TerrestrialDeliverySystemDescriptor *)d;
                  int Source = cSource::FromData(cSource::stTerr);
                  int Frequency = Frequencies[0] = sd->getFrequency() * 10;
-                 static int Bandwidths[] = { BANDWIDTH_8_MHZ, BANDWIDTH_7_MHZ, BANDWIDTH_6_MHZ, BANDWIDTH_AUTO, BANDWIDTH_AUTO, BANDWIDTH_AUTO, BANDWIDTH_AUTO, BANDWIDTH_AUTO };
+                 static int Bandwidths[] = { DVBFE_BANDWIDTH_8_MHZ, DVBFE_BANDWIDTH_7_MHZ, DVBFE_BANDWIDTH_6_MHZ, DVBFE_BANDWIDTH_5_MHZ, DVBFE_BANDWIDTH_AUTO, DVBFE_BANDWIDTH_AUTO, DVBFE_BANDWIDTH_AUTO, DVBFE_BANDWIDTH_AUTO };
                  int Bandwidth = Bandwidths[sd->getBandwidth()];
-                 static int Constellations[] = { QPSK, QAM_16, QAM_64, QAM_AUTO };
+                 static int Constellations[] = { DVBFE_MOD_QPSK, DVBFE_MOD_QAM16, DVBFE_MOD_QAM64, DVBFE_MOD_AUTO };
                  int Constellation = Constellations[sd->getConstellation()];
-                 static int Hierarchies[] = { HIERARCHY_NONE, HIERARCHY_1, HIERARCHY_2, HIERARCHY_4, HIERARCHY_AUTO, HIERARCHY_AUTO, HIERARCHY_AUTO, HIERARCHY_AUTO };
-                 int Hierarchy = Hierarchies[sd->getHierarchy()];
-                 static int CodeRates[] = { FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8, FEC_AUTO, FEC_AUTO, FEC_AUTO };
+                 static int CodeRates[] = { DVBFE_FEC_1_2, DVBFE_FEC_2_3, DVBFE_FEC_3_4, DVBFE_FEC_5_6, DVBFE_FEC_7_8, DVBFE_FEC_AUTO, DVBFE_FEC_AUTO, DVBFE_FEC_AUTO };
                  int CodeRateHP = CodeRates[sd->getCodeRateHP()];
                  int CodeRateLP = CodeRates[sd->getCodeRateLP()];
-                 static int GuardIntervals[] = { GUARD_INTERVAL_1_32, GUARD_INTERVAL_1_16, GUARD_INTERVAL_1_8, GUARD_INTERVAL_1_4 };
+                 static int GuardIntervals[] = { DVBFE_GUARD_INTERVAL_1_32, DVBFE_GUARD_INTERVAL_1_16, DVBFE_GUARD_INTERVAL_1_8, DVBFE_GUARD_INTERVAL_1_4 };
                  int GuardInterval = GuardIntervals[sd->getGuardInterval()];
-                 static int TransmissionModes[] = { TRANSMISSION_MODE_2K, TRANSMISSION_MODE_8K, TRANSMISSION_MODE_AUTO, TRANSMISSION_MODE_AUTO };
+                 static int TransmissionModes[] = { DVBFE_TRANSMISSION_MODE_2K, DVBFE_TRANSMISSION_MODE_4K, DVBFE_TRANSMISSION_MODE_8K, DVBFE_TRANSMISSION_MODE_AUTO };
                  int TransmissionMode = TransmissionModes[sd->getTransmissionMode()];
+                 static int Alphas[] = { DVBFE_ALPHA_1, DVBFE_ALPHA_2, DVBFE_ALPHA_4 };
+                 static int Priorities[] = { DVBFE_STREAM_PRIORITY_LP, DVBFE_STREAM_PRIORITY_HP };
+                 int Priority = Priorities[sd->getPriority()];
+                 int Alpha = 0;
+                 int Hierarchy = DVBFE_HIERARCHY_OFF;
+                 if (sd->getHierarchy() & 3) {
+                    Hierarchy = DVBFE_HIERARCHY_ON;
+                    Alpha = Alphas[sd->getHierarchy() & 3];
+                    }
+
                  if (ThisNIT >= 0) {
                     for (int n = 0; n < NumFrequencies; n++) {
                         if (ISTRANSPONDER(Frequencies[n] / 1000000, Transponder())) {
@@ -263,7 +277,7 @@  void cNitFilter::Process(u_short Pid, u_
                                   }
                               }
                            if (ISTRANSPONDER(Frequency / 1000000, Transponder())) // only modify channels if we're actually receiving this transponder
-                              Channel->SetTerrTransponderData(Source, Frequency, Bandwidth, Constellation, Hierarchy, CodeRateHP, CodeRateLP, GuardInterval, TransmissionMode);
+                              Channel->SetTerrTransponderData(Source, Frequency, Bandwidth, Constellation, Hierarchy, CodeRateHP, CodeRateLP, GuardInterval, TransmissionMode, Alpha, Priority);
                            }
                         found = true;
                         }
@@ -271,12 +285,12 @@  void cNitFilter::Process(u_short Pid, u_
                        for (int n = 0; n < NumFrequencies; n++) {
                            cChannel *Channel = new cChannel;
                            Channel->SetId(ts.getOriginalNetworkId(), ts.getTransportStreamId(), 0, 0);
-                           if (Channel->SetTerrTransponderData(Source, Frequencies[n], Bandwidth, Constellation, Hierarchy, CodeRateHP, CodeRateLP, GuardInterval, TransmissionMode))
+                           if (Channel->SetTerrTransponderData(Source, Frequencies[n], Bandwidth, Constellation, Hierarchy, CodeRateHP, CodeRateLP, GuardInterval, TransmissionMode, Alpha, Priority))
                               EITScanner.AddTransponder(Channel);
                            else
                               delete Channel;
                            }
-                        }
+                       }
                     }
                  }
                  break;
diff -Nup ../vdr-1.5.10-orig/pat.c ./pat.c
--- ../vdr-1.5.10-orig/pat.c	2007-09-02 12:44:19.000000000 +0200
+++ ./pat.c	2007-10-14 17:22:27.000000000 +0200
@@ -431,6 +431,9 @@  void cPatFilter::Process(u_short Pid, u_
                          }
                       }
                       break;
+              case 0x1b: //MPEG4
+                      Vpid = VPID_TO_H264(stream.getPid());
+                      break;
               //default: printf("PID: %5d %5d %2d %3d %3d\n", pmt.getServiceId(), stream.getPid(), stream.getStreamType(), pmt.getVersionNumber(), Channel->Number());//XXX
               }
             for (SI::Loop::Iterator it; (d = (SI::CaDescriptor*)stream.streamDescriptors.getNext(it, SI::CaDescriptorTag)); ) {
diff -Nup ../vdr-1.5.10-orig/recorder.c ./recorder.c
--- ../vdr-1.5.10-orig/recorder.c	2007-02-24 17:36:24.000000000 +0100
+++ ./recorder.c	2007-02-25 19:22:13.000000000 +0100
@@ -127,7 +127,7 @@  void cFileWriter::Action(void)
 // --- cRecorder -------------------------------------------------------------
 
 cRecorder::cRecorder(const char *FileName, tChannelID ChannelID, int Priority, int VPid, const int *APids, const int *DPids, const int *SPids)
-:cReceiver(ChannelID, Priority, VPid, APids, Setup.UseDolbyDigital ? DPids : NULL, SPids)
+:cReceiver(ChannelID, Priority, VPID_FROM_ANY(VPid), APids, Setup.UseDolbyDigital ? DPids : NULL, SPids)
 ,cThread("recording")
 {
   // Make sure the disk is up and running:
diff -Nup ../vdr-1.5.10-orig/recording.c ./recording.c
--- ../vdr-1.5.10-orig/recording.c	2007-10-14 12:21:54.000000000 +0200
+++ ./recording.c	2007-10-14 17:22:27.000000000 +0200
@@ -1518,11 +1518,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;
@@ -1530,17 +1530,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 -------------------------------------------------------------
diff -Nup ../vdr-1.5.10-orig/recording.h ./recording.h
--- ../vdr-1.5.10-orig/recording.h	2007-10-14 12:11:34.000000000 +0200
+++ ./recording.h	2007-10-14 17:22:27.000000000 +0200
@@ -239,11 +239,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);
diff -Nup ../vdr-1.5.10-orig/remux.c ./remux.c
--- ../vdr-1.5.10-orig/remux.c	2007-09-22 14:08:22.000000000 +0200
+++ ./remux.c	2007-10-14 17:28:45.000000000 +0200
@@ -19,6 +19,8 @@ 
 #include "channels.h"
 #include "shutdown.h"
 #include "tools.h"
+#include "recording.h"
+#include "h264parser.h"
 
 ePesHeader AnalyzePesHeader(const uchar *Data, int Count, int &PesPayloadOffset, bool *ContinuationHeader)
 {
@@ -100,8 +102,9 @@  protected:
   int suppressedLogMessages;
   bool LogAllowed(void);
   void DroppedData(const char *Reason, int Count) { LOG("%s (dropped %d bytes)", Reason, Count); }
+  virtual int Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count, int CapacityNeeded);
 public:
-  static int Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count, int CapacityNeeded);
+  static int PutAllOrNothing(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count, int CapacityNeeded);
   cRepacker(void);
   virtual ~cRepacker() {}
   virtual void Reset(void) { initiallySyncing = true; }
@@ -138,6 +141,11 @@  bool cRepacker::LogAllowed(void)
 
 int cRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count, int CapacityNeeded)
 {
+  return PutAllOrNothing(ResultBuffer, Data, Count, CapacityNeeded);
+}
+
+int cRepacker::PutAllOrNothing(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count, int CapacityNeeded)
+{
   if (CapacityNeeded >= Count && ResultBuffer->Free() < CapacityNeeded) {
      esyslog("ERROR: possible result buffer overflow, dropped %d out of %d byte", CapacityNeeded, CapacityNeeded);
      return 0;
@@ -156,7 +164,7 @@  protected:
   int packetTodo;
   uchar fragmentData[6 + 65535 + 3];
   int fragmentLen;
-  uchar pesHeader[6 + 3 + 255 + 3];
+  uchar pesHeader[6 + 3 + 255 + 5 + 3]; // 5: H.264 AUD
   int pesHeaderLen;
   uchar pesHeaderBackup[6 + 3 + 255];
   int pesHeaderBackupLen;
@@ -164,7 +172,7 @@  protected:
   uint32_t localScanner;
   int localStart;
   bool PushOutPacket(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count);
-  virtual int QuerySnoopSize() { return 4; }
+  virtual int QuerySnoopSize(void) { return 4; }
   virtual void Reset(void);
   };
 
@@ -238,6 +246,132 @@  bool cCommonRepacker::PushOutPacket(cRin
   return true;
 }
 
+// --- cAudGenerator ---------------------------------------------------------
+
+class cAudGenerator {
+private:
+  H264::cSimpleBuffer buffer;
+  int overflowByteCount;
+  H264::cSliceHeader::eAccessUnitType accessUnitType;
+  int sliceTypes;
+public:
+  cAudGenerator(void);
+  void CollectSliceType(const H264::cSliceHeader *SH);
+  int CollectData(const uchar *Data, int Count);
+  void Generate(cRingBufferLinear *const ResultBuffer);
+};
+
+cAudGenerator::cAudGenerator()
+  : buffer(MAXFRAMESIZE)
+{
+  overflowByteCount = 0;
+  accessUnitType = H264::cSliceHeader::Frame;
+  sliceTypes = 0;
+}
+
+int cAudGenerator::CollectData(const uchar *Data, int Count)
+{
+  // buffer frame data until AUD can be generated
+  int n = buffer.Put(Data, Count);
+  overflowByteCount += (Count - n);
+  // always report "success" as an error message will be shown in Generate()
+  return Count;
+}
+
+void cAudGenerator::CollectSliceType(const H264::cSliceHeader *SH)
+{
+  if (!SH)
+     return;
+  // remember type of current access unit 
+  accessUnitType = SH->GetAccessUnitType();
+  // translate slice_type into part of primary_pic_type and merge them
+  switch (SH->slice_type) {
+    case 2: // I
+    case 7: // I only => I 
+         sliceTypes |= 0x10000;
+         break;
+    case 0: // P
+    case 5: // P only => I, P
+         sliceTypes |= 0x11000;
+         break;
+    case 1: // B
+    case 6: // B only => I, P, B
+         sliceTypes |= 0x11100;
+         break;
+    case 4: // SI
+    case 9: // SI only => SI
+         sliceTypes |= 0x00010;
+         break;
+    case 3: // SP
+    case 8: // SP only => SI, SP
+         sliceTypes |= 0x00011;
+         break;
+    }
+}
+
+void cAudGenerator::Generate(cRingBufferLinear *const ResultBuffer)
+{
+  int primary_pic_type;
+  // translate the merged primary_pic_type parts into primary_pic_type
+  switch (sliceTypes) {
+    case 0x10000: // I
+         primary_pic_type = 0;
+         break;
+    case 0x11000: // I, P
+         primary_pic_type = 1;
+         break;
+    case 0x11100: // I, P, B
+         primary_pic_type = 2;
+         break;
+    case 0x00010: // SI
+         primary_pic_type = 3;
+         break;
+    case 0x00011: // SI, SP
+         primary_pic_type = 4;
+         break;
+    case 0x10010: // I, SI
+         primary_pic_type = 5;
+         break;
+    case 0x11011: // I, SI, P, SP
+    case 0x10011: // I, SI, SP
+    case 0x11010: // I, SI, P
+         primary_pic_type = 6;
+         break;
+    case 0x11111: // I, SI, P, SP, B
+    case 0x11110: // I, SI, P, B
+         primary_pic_type = 7;
+         break;
+    default:
+         primary_pic_type = -1; // frame without slices?
+    }
+  // drop an incorrect frame
+  if (primary_pic_type < 0)
+     esyslog("ERROR: cAudGenerator::Generate(): dropping frame without slices");
+  else {
+     // drop a partitial frame
+     if (overflowByteCount > 0) 
+        esyslog("ERROR: cAudGenerator::Generate(): frame exceeds MAXFRAMESIZE bytes (required size: %d bytes), dropping frame", buffer.Size() + overflowByteCount);
+     else {
+        int Count;
+        uchar *Data = buffer.Get(Count);
+        int PesPayloadOffset = 0;
+        AnalyzePesHeader(Data, Count, PesPayloadOffset);
+        // enter primary_pic_type into AUD
+        Data[ PesPayloadOffset + 4 ] |= primary_pic_type << 5;
+        // mangle the "start code" to pass the information that this access unit is a
+        // bottom field to ScanVideoPacket() where this modification will be reverted.
+        if (accessUnitType == H264::cSliceHeader::BottomField)
+           Data[ PesPayloadOffset + 3 ] |= 0x80;
+        // store the buffered frame
+        cRepacker::PutAllOrNothing(ResultBuffer, Data, Count, Count);
+        }
+     }
+  // prepare for next run
+  buffer.Clear();
+  overflowByteCount = 0;
+  sliceTypes = 0;
+}
+
 // --- cVideoRepacker --------------------------------------------------------
 
 class cVideoRepacker : public cCommonRepacker {
@@ -248,6 +382,13 @@  private:
     scanPicture
     };
   int state;
+  H264::cParser *h264Parser;
+  int sliceSeen;
+  bool audSeen;
+  cAudGenerator *audGenerator;
+  void CheckAudGeneration(bool SliceNalUnitType, bool SyncPoint, const uchar *const Data, cRingBufferLinear *const ResultBuffer, const uchar *&Payload, const uchar StreamID, const ePesHeader MpegLevel);
+  void PushOutCurrentFrameAndStartNewPacket(const uchar *const Data, cRingBufferLinear *const ResultBuffer, const uchar *&Payload, const uchar StreamID, const ePesHeader MpegLevel);
+  void HandleNalUnit(const uchar *const Data, cRingBufferLinear *const ResultBuffer, const uchar *&Payload, const uchar StreamID, const ePesHeader MpegLevel, const uchar *&NalPayload);
   void HandleStartCode(const uchar *const Data, cRingBufferLinear *const ResultBuffer, const uchar *&Payload, const uchar StreamID, const ePesHeader MpegLevel);
   inline bool ScanDataForStartCodeSlow(const uchar *const Data);
   inline bool ScanDataForStartCodeFast(const uchar *&Data, const uchar *Limit);
@@ -256,30 +397,155 @@  private:
   inline bool ScanForEndOfPictureSlow(const uchar *&Data);
   inline bool ScanForEndOfPictureFast(const uchar *&Data, const uchar *Limit);
   inline bool ScanForEndOfPicture(const uchar *&Data, const uchar *Limit);
+  void CollectNalUnitData(const uchar *Data, int Count);
+protected:
+  virtual int Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count, int CapacityNeeded);
 public:
-  cVideoRepacker(void);
+  cVideoRepacker(bool H264);
+  ~cVideoRepacker();
   virtual void Reset(void);
   virtual void Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count);
   virtual int BreakAt(const uchar *Data, int Count);
   };
 
-cVideoRepacker::cVideoRepacker(void)
+cVideoRepacker::cVideoRepacker(bool H264)
 {
+  h264Parser = (H264 ? new H264::cParser() : 0);
+  audGenerator = 0;
   Reset();
 }
 
+cVideoRepacker::~cVideoRepacker()
+{
+  delete h264Parser;
+  delete audGenerator;
+}
+
 void cVideoRepacker::Reset(void)
 {
   cCommonRepacker::Reset();
+  if (h264Parser)
+     h264Parser->Reset();
   scanner = 0xFFFFFFFF;
   state = syncing;
+  sliceSeen = -1;
+  audSeen = false;
+  delete audGenerator;
+  audGenerator = 0;
 }
 
-void cVideoRepacker::HandleStartCode(const uchar *const Data, cRingBufferLinear *const ResultBuffer, const uchar *&Payload, const uchar StreamID, const ePesHeader MpegLevel)
+int cVideoRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count, int CapacityNeeded)
 {
-  // synchronisation is detected some bytes after frame start.
-  const int SkippedBytesLimit = 4;
+  if (!audGenerator)
+     return cCommonRepacker::Put(ResultBuffer, Data, Count, CapacityNeeded);
+
+  return audGenerator->CollectData(Data, Count);
+}
 
+void cVideoRepacker::CollectNalUnitData(const uchar *Data, int Count)
+{
+  if (h264Parser)
+     h264Parser->PutNalUnitData(Data, Count);
+}
+
+void cVideoRepacker::HandleNalUnit(const uchar *const Data, cRingBufferLinear *const ResultBuffer, const uchar *&Payload, const uchar StreamID, const ePesHeader MpegLevel, const uchar *&NalPayload)
+{
+  // valid NAL units start with a zero bit
+  if (*Data & 0x80) {
+     LOG("cVideoRepacker: found invalid NAL unit: stream seems to be scrambled or not demultiplexed");
+     return;
+     }
+
+  // collect NAL unit's remaining data and process it 
+  CollectNalUnitData(NalPayload, Data - 3 - NalPayload);
+  h264Parser->Process();
+
+  // collect 0x00 0x00 0x01 for current NAL unit
+  static const uchar InitPayload[3] = { 0x00, 0x00, 0x01 };
+  CollectNalUnitData(InitPayload, sizeof (InitPayload));
+  NalPayload = Data;
+
+  // which kind of NAL unit have we got?
+  const int nal_unit_type = *Data & 0x1F;
+  switch (nal_unit_type) {
+    case 1: // coded slice of a non-IDR picture
+    case 2: // coded slice data partition A
+    case 5: // coded slice of an IDR picture
+         CheckAudGeneration(true, false, Data, ResultBuffer, Payload, StreamID, MpegLevel);
+         break;
+    case 3: // coded slice data partition B
+    case 4: // coded slice data partition C
+    case 19: // coded slice of an auxiliary coded picture without partitioning
+         break;
+    case 6: // supplemental enhancement information (SEI)
+    case 7: // sequence parameter set
+    case 8: // picture parameter set
+    case 10: // end of sequence
+    case 11: // end of stream
+    case 13: // sequence parameter set extension
+         CheckAudGeneration(false, nal_unit_type == 7, Data, ResultBuffer, Payload, StreamID, MpegLevel);
+         break;
+    case 12: // filler data
+         break;
+    case 14 ... 18: // reserved
+         CheckAudGeneration(false, false, Data, ResultBuffer, Payload, StreamID, MpegLevel);
+    case 20 ... 23: // reserved
+         LOG("cVideoRepacker: found reserved NAL unit type: stream seems to be scrambled");
+         break;
+    case 0: // unspecified
+    case 24 ... 31: // unspecified
+         LOG("cVideoRepacker: found unspecified NAL unit type: stream seems to be scrambled");
+         break;
+    case 9: { // access unit delimiter
+         audSeen = true;
+         CheckAudGeneration(false, true, Data, ResultBuffer, Payload, StreamID, MpegLevel);
+         // mangle the "start code" to pass the information that the next access unit will be
+         // a bottom field to ScanVideoPacket() where this modification will be reverted.
+         const H264::cSliceHeader *SH = h264Parser->Context().CurrentSlice();
+         if (SH && SH->GetAccessUnitType() == H264::cSliceHeader::TopField)
+            *(uchar *)Data |= 0x80;
+         }
+         break;
+    }
+}
+
+void cVideoRepacker::CheckAudGeneration(bool SliceNalUnitType, bool SyncPoint, const uchar *const Data, cRingBufferLinear *const ResultBuffer, const uchar *&Payload, const uchar StreamID, const ePesHeader MpegLevel)
+{
+  // we cannot generate anything until we have reached the synchronisation point
+  if (sliceSeen < 0 && !SyncPoint)
+     return;
+  // detect transition from slice to non-slice NAL units
+  const bool WasSliceSeen = (sliceSeen != false);
+  const bool IsSliceSeen = SliceNalUnitType;
+  sliceSeen = IsSliceSeen;
+  // collect slice types for AUD generation
+  if (WasSliceSeen && audGenerator)
+     audGenerator->CollectSliceType(h264Parser->Context().CurrentSlice());
+  // handle access unit delimiter at the transition from slice to non-slice NAL units
+  if (WasSliceSeen && !IsSliceSeen) {
+     // an Access Unit Delimiter indicates that the current picture is done. So let's
+     // push out the current frame to start a new packet for the next picture.
+     PushOutCurrentFrameAndStartNewPacket(Data, ResultBuffer, Payload, StreamID, MpegLevel);
+     if (state == findPicture) {
+        // go on with scanning the picture data
+        state++;
+        }
+     // generate the AUD and push out the buffered frame
+     if (audGenerator) {
+        audGenerator->Generate(ResultBuffer);
+        if (audSeen) {
+           // we nolonger need to generate AUDs as they are part of the stream
+           delete audGenerator;
+           audGenerator = 0;
+           }
+        }
+     else if (!audSeen) // we do need to generate AUDs
+        audGenerator = new cAudGenerator;
+     }
+}
+
+void cVideoRepacker::HandleStartCode(const uchar *const Data, cRingBufferLinear *const ResultBuffer, const uchar *&Payload, const uchar StreamID, const ePesHeader MpegLevel)
+{
   // which kind of start code have we got?
   switch (*Data) {
     case 0xB9 ... 0xFF: // system start codes
@@ -298,65 +564,9 @@  void cVideoRepacker::HandleStartCode(con
     case 0xB3: // sequence header code
     case 0xB8: // group start code
     case 0x00: // picture start code
-         if (state == scanPicture) {
-            // the above start codes indicate that the current picture is done. So
-            // push out the packet to start a new packet for the next picuture. If
-            // the byte count get's negative then the current buffer ends in a
-            // partitial start code that must be stripped off, as it shall be put
-            // in the next packet.
-            PushOutPacket(ResultBuffer, Payload, Data - 3 - Payload);
-            // go on with syncing to the next picture
-            state = syncing;
-            }
-         if (state == syncing) {
-            if (initiallySyncing) // omit report for the typical initial case
-               initiallySyncing = false;
-            else if (skippedBytes > SkippedBytesLimit) // report that syncing dropped some bytes
-               LOG("cVideoRepacker: skipped %d bytes to sync on next picture", skippedBytes - SkippedBytesLimit);
-            skippedBytes = 0;
-            // if there is a PES header available, then use it ...
-            if (pesHeaderBackupLen > 0) {
-               // ISO 13818-1 says:
-               // In the case of video, if a PTS is present in a PES packet header
-               // it shall refer to the access unit containing the first picture start
-               // code that commences in this PES packet. A picture start code commences
-               // in PES packet if the first byte of the picture start code is present
-               // in the PES packet.
-               memcpy(pesHeader, pesHeaderBackup, pesHeaderBackupLen);
-               pesHeaderLen = pesHeaderBackupLen;
-               pesHeaderBackupLen = 0;
-               }
-            else {
-               // ... otherwise create a continuation PES header
-               pesHeaderLen = 0;
-               pesHeader[pesHeaderLen++] = 0x00;
-               pesHeader[pesHeaderLen++] = 0x00;
-               pesHeader[pesHeaderLen++] = 0x01;
-               pesHeader[pesHeaderLen++] = StreamID; // video stream ID
-               pesHeader[pesHeaderLen++] = 0x00; // length still unknown
-               pesHeader[pesHeaderLen++] = 0x00; // length still unknown
-
-               if (MpegLevel == phMPEG2) {
-                  pesHeader[pesHeaderLen++] = 0x80;
-                  pesHeader[pesHeaderLen++] = 0x00;
-                  pesHeader[pesHeaderLen++] = 0x00;
-                  }
-               else
-                  pesHeader[pesHeaderLen++] = 0x0F;
-               }
-            // append the first three bytes of the start code
-            pesHeader[pesHeaderLen++] = 0x00;
-            pesHeader[pesHeaderLen++] = 0x00;
-            pesHeader[pesHeaderLen++] = 0x01;
-            // the next packet's payload will begin with the fourth byte of
-            // the start code (= the actual code)
-            Payload = Data;
-            // as there is no length information available, assume the
-            // maximum we can hold in one PES packet
-            packetTodo = maxPacketSize - pesHeaderLen;
-            // go on with finding the picture data
-            state++;
-            }
+         // the above start codes indicate that the current picture is done. So let's
+         // push out the current frame to start a new packet for the next picture.
+         PushOutCurrentFrameAndStartNewPacket(Data, ResultBuffer, Payload, StreamID, MpegLevel);
          break;
     case 0x01 ... 0xAF: // slice start codes
          if (state == findPicture) {
@@ -367,6 +577,81 @@  void cVideoRepacker::HandleStartCode(con
     }
 }
 
+void cVideoRepacker::PushOutCurrentFrameAndStartNewPacket(const uchar *const Data, cRingBufferLinear *const ResultBuffer, const uchar *&Payload, const uchar StreamID, const ePesHeader MpegLevel)
+{
+  // synchronisation is detected some bytes after frame start.
+  const int SkippedBytesLimit = 4;
+
+  if (state == scanPicture) {
+     // picture data has been found so let's push out the current frame.
+     // If the byte count get's negative then the current buffer ends in a
+     // partitial start code that must be stripped off, as it shall be put
+     // in the next packet.
+     PushOutPacket(ResultBuffer, Payload, Data - 3 - Payload);
+     // go on with syncing to the next picture
+     state = syncing;
+     }
+  // when already synced to a picture, just go on collecting data 
+  if (state != syncing)
+     return;
+  // we're synced to a picture so prepare a new packet
+  if (initiallySyncing) // omit report for the typical initial case
+     initiallySyncing = false;
+  else if (skippedBytes > SkippedBytesLimit) // report that syncing dropped some bytes
+     LOG("cVideoRepacker: skipped %d bytes to sync on next picture", skippedBytes - SkippedBytesLimit);
+  skippedBytes = 0;
+  // if there is a PES header available, then use it ...
+  if (pesHeaderBackupLen > 0) {
+     // ISO 13818-1 says:
+     // In the case of video, if a PTS is present in a PES packet header
+     // it shall refer to the access unit containing the first picture start
+     // code that commences in this PES packet. A picture start code commences
+     // in PES packet if the first byte of the picture start code is present
+     // in the PES packet.
+     memcpy(pesHeader, pesHeaderBackup, pesHeaderBackupLen);
+     pesHeaderLen = pesHeaderBackupLen;
+     pesHeaderBackupLen = 0;
+     }
+  else {
+     // ... otherwise create a continuation PES header
+     pesHeaderLen = 0;
+     pesHeader[pesHeaderLen++] = 0x00;
+     pesHeader[pesHeaderLen++] = 0x00;
+     pesHeader[pesHeaderLen++] = 0x01;
+     pesHeader[pesHeaderLen++] = StreamID; // video stream ID
+     pesHeader[pesHeaderLen++] = 0x00; // length still unknown
+     pesHeader[pesHeaderLen++] = 0x00; // length still unknown
+
+     if (MpegLevel == phMPEG2) {
+        pesHeader[pesHeaderLen++] = 0x80;
+        pesHeader[pesHeaderLen++] = 0x00;
+        pesHeader[pesHeaderLen++] = 0x00;
+        }
+     else
+        pesHeader[pesHeaderLen++] = 0x0F;
+     }
+  // add an AUD in H.264 mode when not present in stream
+  if (h264Parser && !audSeen) {
+     pesHeader[pesHeaderLen++] = 0x00;
+     pesHeader[pesHeaderLen++] = 0x00;
+     pesHeader[pesHeaderLen++] = 0x01;
+     pesHeader[pesHeaderLen++] = 0x09; // access unit delimiter
+     pesHeader[pesHeaderLen++] = 0x10; // will be filled later
+     }
+  // append the first three bytes of the start code
+  pesHeader[pesHeaderLen++] = 0x00;
+  pesHeader[pesHeaderLen++] = 0x00;
+  pesHeader[pesHeaderLen++] = 0x01;
+  // the next packet's payload will begin with the fourth byte of
+  // the start code (= the actual code)
+  Payload = Data;
+  // as there is no length information available, assume the
+  // maximum we can hold in one PES packet
+  packetTodo = maxPacketSize - pesHeaderLen;
+  // go on with finding the picture data
+  state++;
+}
+
 bool cVideoRepacker::ScanDataForStartCodeSlow(const uchar *const Data)
 {
   scanner <<= 8;
@@ -458,14 +743,19 @@  void cVideoRepacker::Repack(cRingBufferL
   const uchar *data = Data + done;
   // remember start of the data
   const uchar *payload = data;
+  const uchar *NalPayload = payload;
 
   while (todo > 0) {
         // collect number of skipped bytes while syncing
         if (state <= syncing)
            skippedBytes++;
         // did we reach a start code?
-        if (ScanDataForStartCode(data, done, todo))
-           HandleStartCode(data, ResultBuffer, payload, Data[3], mpegLevel);
+        if (ScanDataForStartCode(data, done, todo)) {
+           if (h264Parser)
+              HandleNalUnit(data, ResultBuffer, payload, Data[3], mpegLevel, NalPayload);
+           else
+              HandleStartCode(data, ResultBuffer, payload, Data[3], mpegLevel);
+           }
         // move on
         data++;
         done++;
@@ -568,6 +858,8 @@  void cVideoRepacker::Repack(cRingBufferL
         fragmentLen += bite;
         }
      }
+  // always collect remaining NAL unit data (may be needed for syncing)
+  CollectNalUnitData(NalPayload, data - NalPayload);
   // report that syncing dropped some bytes
   if (skippedBytes > SkippedBytesLimit) {
      if (!initiallySyncing) // omit report for the typical initial case
@@ -581,13 +873,22 @@  bool cVideoRepacker::ScanForEndOfPicture
   localScanner <<= 8;
   localScanner |= *Data++;
   // check start codes which follow picture data
-  switch (localScanner) {
-    case 0x00000100: // picture start code
-    case 0x000001B8: // group start code
-    case 0x000001B3: // sequence header code
-    case 0x000001B7: // sequence end code
-         return true;
-    }
+  if (h264Parser) {
+     int nal_unit_type = localScanner & 0x1F;
+     switch (nal_unit_type) {
+       case 9: // access unit delimiter
+            return true;
+       }
+     }
+  else {
+     switch (localScanner) {
+       case 0x00000100: // picture start code
+       case 0x000001B8: // group start code
+       case 0x000001B3: // sequence header code
+       case 0x000001B7: // sequence end code
+            return true;
+       }
+     }
   return false;
 }
 
@@ -601,15 +902,27 @@  bool cVideoRepacker::ScanForEndOfPicture
         else {
            localScanner = 0x00000100 | *++Data;
            // check start codes which follow picture data
-           switch (localScanner) {
-             case 0x00000100: // picture start code
-             case 0x000001B8: // group start code
-             case 0x000001B3: // sequence header code
-             case 0x000001B7: // sequence end code
-                  Data++;
-                  return true;
-             default:
-                  Data += 3;
+           if (h264Parser) {
+              int nal_unit_type = localScanner & 0x1F;
+              switch (nal_unit_type) {
+                case 9: // access unit delimiter
+                     Data++;
+                     return true;
+                default:
+                     Data += 3;
+                }
+              }
+           else {
+              switch (localScanner) {
+                case 0x00000100: // picture start code
+                case 0x000001B8: // group start code
+                case 0x000001B3: // sequence header code
+                case 0x000001B7: // sequence end code
+                     Data++;
+                     return true;
+                default:
+                     Data += 3;
+                }
              }
            }
         }
@@ -1521,7 +1834,7 @@  void cTS2PES::store(uint8_t *Data, int C
   if (repacker)
      repacker->Repack(resultBuffer, Data, Count);
   else
-     cRepacker::Put(resultBuffer, Data, Count, Count);
+     cRepacker::PutAllOrNothing(resultBuffer, Data, Count, Count);
 }
 
 void cTS2PES::reset_ipack(void)
@@ -1841,7 +2154,7 @@  void cTS2PES::ts_to_pes(const uint8_t *B
         // Enable this if you are having problems with signal quality.
         // These are the errors I used to get with Nova-T when antenna
         // was not positioned correcly (not transport errors). //tvr
-        //dsyslog("TS continuity error (%d)", ccCounter);
+        dsyslog("TS continuity error (%d)", ccCounter);
         }
      ccCounter = Buf[3] & CONT_CNT_MASK;
      }
@@ -1873,12 +2186,15 @@  void cTS2PES::ts_to_pes(const uint8_t *B
 
 #define RESULTBUFFERSIZE KILOBYTE(256)
 
-cRemux::cRemux(int VPid, const int *APids, const int *DPids, const int *SPids, bool ExitOnFailure)
+cRemux::cRemux(int VPid, const int *APids, const int *DPids, const int *SPids, bool ExitOnFailure, bool SyncEarly)
 {
+  h264 = VPID_IS_H264(VPid);
+  VPid = VPID_FROM_ANY(VPid);
   exitOnFailure = ExitOnFailure;
   noVideo = VPid == 0 || VPid == 1 || VPid == 0x1FFF;
   numUPTerrors = 0;
   synced = false;
+  syncEarly = SyncEarly;
   skipped = 0;
   numTracks = 0;
   resultSkipped = 0;
@@ -1887,7 +2203,7 @@  cRemux::cRemux(int VPid, const int *APid
   if (VPid)
 #define TEST_cVideoRepacker
 #ifdef TEST_cVideoRepacker
-     ts2pes[numTracks++] = new cTS2PES(VPid, resultBuffer, IPACKS, 0xE0, 0x00, new cVideoRepacker);
+     ts2pes[numTracks++] = new cTS2PES(VPid, resultBuffer, IPACKS, 0xE0, 0x00, new cVideoRepacker(h264));
 #else
      ts2pes[numTracks++] = new cTS2PES(VPid, resultBuffer, IPACKS, 0xE0);
 #endif
@@ -1937,6 +2253,23 @@  int cRemux::GetPacketLength(const uchar 
   return -1;
 }
 
+bool cRemux::IsFrameH264(const uchar *Data, int Length)
+{
+  int PesPayloadOffset;
+  const uchar *limit = Data + Length;
+  if (AnalyzePesHeader(Data, Length, PesPayloadOffset) <= phInvalid)
+     return false; // neither MPEG1 nor MPEG2
+
+  Data += PesPayloadOffset + 3; // move to video payload and skip 00 00 01
+  if (Data < limit) {
+     // cVideoRepacker ensures that in case of H264 we will see an access unit delimiter here
+     if (0x01 == Data[-1] && 9 == Data[0] && 0x00 == Data[-2] && 0x00 == Data[-3])
+        return true;
+     }
+
+  return false;
+}
+
 int cRemux::ScanVideoPacket(const uchar *Data, int Count, int Offset, uchar &PictureType)
 {
   // Scans the video packet starting at Offset and returns its length.
@@ -1955,23 +2288,67 @@  int cRemux::ScanVideoPacket(const uchar 
            if (p[-2] || p[-1] || p[0] != 0x01)
               pLimit = 0; // skip scanning: packet doesn't start with 0x000001
            else {
-              switch (p[1]) {
-                case SC_SEQUENCE:
-                case SC_GROUP:
-                case SC_PICTURE:
-                     break;
-                default: // skip scanning: packet doesn't start a new sequence, group or picture
-                     pLimit = 0;
-                }
+              if (h264) {
+                 int nal_unit_type = p[1] & 0x1F;
+                 switch (nal_unit_type) {
+                   case 9: // access unit delimiter
+                        // when the MSB in p[1] is set (which violates H.264) then this is a hint
+                        // from cVideoRepacker::HandleNalUnit() that this bottom field shall not
+                        // be reported as picture.
+                        if (p[1] & 0x80)
+                           ((uchar *)p)[1] &= ~0x80; // revert the hint and fall through
+                        else
+                           break;
+                   default: // skip scanning: packet doesn't start a new picture
+                        pLimit = 0;
+                   }
+                 }
+              else {
+                 switch (p[1]) {
+                   case SC_SEQUENCE:
+                   case SC_GROUP:
+                   case SC_PICTURE:
+                        break;
+                   default: // skip scanning: packet doesn't start a new sequence, group or picture
+                        pLimit = 0;
+                   }
+                 }
               }
            }
 #endif
         while (p < pLimit && (p = (const uchar *)memchr(p, 0x01, pLimit - p))) {
               if (!p[-2] && !p[-1]) { // found 0x000001
-                 switch (p[1]) {
-                   case SC_PICTURE: PictureType = (p[3] >> 3) & 0x07;
-                                    return Length;
-                   }
+                 if (h264) {
+                    int nal_unit_type = p[1] & 0x1F;
+                    switch (nal_unit_type) {
+                      case 9: { // access unit delimiter
+                              int primary_pic_type = p[2] >> 5;
+                              switch (primary_pic_type) {
+                                case 0: // I
+                                case 3: // SI
+                                case 5: // I, SI
+                                     PictureType = I_FRAME;
+                                     break;
+                                case 1: // I, P
+                                case 4: // SI, SP
+                                case 6: // I, SI, P, SP
+                                     PictureType = P_FRAME;
+                                     break;
+                                case 2: // I, P, B
+                                case 7: // I, SI, P, SP, B
+                                     PictureType = B_FRAME;
+                                     break;
+                                }
+                              return Length;
+                              }
+                      }
+                    }
+                 else {
+                    switch (p[1]) {
+                      case SC_PICTURE: PictureType = (p[3] >> 3) & 0x07;
+                                       return Length;
+                      }
+                    }
                  p += 4; // continue scanning after 0x01ssxxyy
                  }
               else
@@ -2080,12 +2457,14 @@  uchar *cRemux::Get(int &Count, uchar *Pi
                         ShutdownHandler.RequestEmergencyExit();
                      }
                   else if (!synced) {
-                     if (pt == I_FRAME) {
+                     if (pt == I_FRAME || syncEarly) {
                         if (PictureType)
                            *PictureType = pt;
                         resultSkipped = i; // will drop everything before this position
-                        SetBrokenLink(data + i, l);
                         synced = true;
+                        if (pt == I_FRAME) // syncEarly: it's ok but there is no need to call SetBrokenLink()
+                           SetBrokenLink(data + i, l);
+else fprintf(stderr, "video: synced early\n");
                         }
                      }
                   else if (Count)
@@ -2098,12 +2477,13 @@  uchar *cRemux::Get(int &Count, uchar *Pi
                l = GetPacketLength(data, resultCount, i);
                if (l < 0)
                   return resultData;
-               if (noVideo) {
+               if (noVideo || !synced && syncEarly) {
                   if (!synced) {
-                     if (PictureType)
+                     if (PictureType && noVideo)
                         *PictureType = I_FRAME;
                      resultSkipped = i; // will drop everything before this position
                      synced = true;
+if (!noVideo) fprintf(stderr, "audio: synced early\n");
                      }
                   else if (Count)
                      return resultData;
diff -Nup ../vdr-1.5.10-orig/remux.h ./remux.h
--- ../vdr-1.5.10-orig/remux.h	2007-09-02 12:19:06.000000000 +0200
+++ ./remux.h	2007-10-14 17:27:40.000000000 +0200
@@ -38,21 +38,25 @@  class cRemux {
 private:
   bool exitOnFailure;
   bool noVideo;
+  bool h264;
   int numUPTerrors;
   bool synced;
+  bool syncEarly;
   int skipped;
   cTS2PES *ts2pes[MAXTRACKS];
   int numTracks;
   cRingBufferLinear *resultBuffer;
   int resultSkipped;
   int GetPid(const uchar *Data);
+  int ScanVideoPacket(const uchar *Data, int Count, int Offset, uchar &PictureType);
 public:
-  cRemux(int VPid, const int *APids, const int *DPids, const int *SPids, bool ExitOnFailure = false);
+  cRemux(int VPid, const int *APids, const int *DPids, const int *SPids, bool ExitOnFailure = false, bool SyncEarly = false);
        ///< Creates a new remuxer for the given PIDs. VPid is the video PID, while
        ///< APids, DPids and SPids are pointers to zero terminated lists of audio,
        ///< dolby and subtitle PIDs (the pointers may be NULL if there is no such
        ///< PID). If ExitOnFailure is true, the remuxer will initiate an "emergency
-       ///< exit" in case of problems with the data stream.
+       ///< exit" in case of problems with the data stream. SyncEarly causes cRemux
+       ///< to sync as soon as a video or audio frame is seen.
   ~cRemux();
   void SetTimeouts(int PutTimeout, int GetTimeout) { resultBuffer->SetTimeouts(PutTimeout, GetTimeout); }
        ///< By default cRemux assumes that Put() and Get() are called from different
@@ -78,7 +82,7 @@  public:
        ///< settings as they are.
   static void SetBrokenLink(uchar *Data, int Length);
   static int GetPacketLength(const uchar *Data, int Count, int Offset);
-  static int ScanVideoPacket(const uchar *Data, int Count, int Offset, uchar &PictureType);
+  static bool IsFrameH264(const uchar *Data, int Length);
   };
 
 #endif // __REMUX_H
diff -Nup ../vdr-1.5.10-orig/sdt.c ./sdt.c
--- ../vdr-1.5.10-orig/sdt.c	2007-06-10 10:50:49.000000000 +0200
+++ ./sdt.c	2007-06-17 18:35:37.000000000 +0200
@@ -55,6 +55,7 @@  void cSdtFilter::Process(u_short Pid, u_
                    case 0x02: // digital radio sound service
                    case 0x04: // NVOD reference service
                    case 0x05: // NVOD time-shifted service
+                   case 0x19: // digital HD television service
                         {
                         char NameBuf[Utf8BufSize(1024)];
                         char ShortNameBuf[Utf8BufSize(1024)];
diff -Nup ../vdr-1.5.10-orig/svdrp.c ./svdrp.c
--- ../vdr-1.5.10-orig/svdrp.c	2007-10-13 12:17:48.000000000 +0200
+++ ./svdrp.c	2007-10-14 17:22:27.000000000 +0200
@@ -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)
diff -Nup ../vdr-1.5.10-orig/tools.c ./tools.c
--- ../vdr-1.5.10-orig/tools.c	2007-10-13 14:00:21.000000000 +0200
+++ ./tools.c	2007-10-14 17:22:27.000000000 +0200
@@ -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"
diff -Nup ../vdr-1.5.10-orig/tools.h ./tools.h
--- ../vdr-1.5.10-orig/tools.h	2007-08-25 16:16:39.000000000 +0200
+++ ./tools.h	2007-08-28 22:25:08.000000000 +0200
@@ -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 {
diff -Nup ../vdr-1.5.10-orig/transfer.c ./transfer.c
--- ../vdr-1.5.10-orig/transfer.c	2007-01-05 11:45:28.000000000 +0100
+++ ./transfer.c	2007-09-01 21:30:01.000000000 +0200
@@ -15,11 +15,11 @@ 
 // --- cTransfer -------------------------------------------------------------
 
 cTransfer::cTransfer(tChannelID ChannelID, int VPid, const int *APids, const int *DPids, const int *SPids)
-:cReceiver(ChannelID, -1, VPid, APids, Setup.UseDolbyDigital ? DPids : NULL, SPids)
+:cReceiver(ChannelID, -1, VPID_FROM_ANY(VPid), APids, Setup.UseDolbyDigital ? DPids : NULL, SPids)
 ,cThread("transfer")
 {
   ringBuffer = new cRingBufferLinear(TRANSFERBUFSIZE, TS_SIZE * 2, true, "Transfer");
-  remux = new cRemux(VPid, APids, Setup.UseDolbyDigital ? DPids : NULL, SPids);
+  remux = new cRemux(VPid, APids, Setup.UseDolbyDigital ? DPids : NULL, SPids, false, true);
 }
 
 cTransfer::~cTransfer()