diff options
| -rw-r--r-- | HISTORY | 10 | ||||
| -rw-r--r-- | po/ca_ES.po | 8 | ||||
| -rw-r--r-- | po/cs_CZ.po | 8 | ||||
| -rw-r--r-- | po/da_DK.po | 8 | ||||
| -rw-r--r-- | po/de_DE.po | 8 | ||||
| -rw-r--r-- | po/el_GR.po | 8 | ||||
| -rw-r--r-- | po/es_ES.po | 8 | ||||
| -rw-r--r-- | po/et_EE.po | 8 | ||||
| -rw-r--r-- | po/fi_FI.po | 8 | ||||
| -rw-r--r-- | po/fr_FR.po | 8 | ||||
| -rw-r--r-- | po/hr_HR.po | 8 | ||||
| -rw-r--r-- | po/hu_HU.po | 8 | ||||
| -rw-r--r-- | po/it_IT.po | 8 | ||||
| -rw-r--r-- | po/lt_LT.po | 8 | ||||
| -rw-r--r-- | po/nl_NL.po | 8 | ||||
| -rw-r--r-- | po/nn_NO.po | 8 | ||||
| -rw-r--r-- | po/pl_PL.po | 8 | ||||
| -rw-r--r-- | po/pt_PT.po | 8 | ||||
| -rw-r--r-- | po/ro_RO.po | 8 | ||||
| -rw-r--r-- | po/ru_RU.po | 8 | ||||
| -rw-r--r-- | po/sk_SK.po | 9 | ||||
| -rw-r--r-- | po/sl_SI.po | 8 | ||||
| -rw-r--r-- | po/sv_SE.po | 8 | ||||
| -rw-r--r-- | po/tr_TR.po | 8 | ||||
| -rw-r--r-- | po/uk_UA.po | 8 | ||||
| -rw-r--r-- | po/zh_CN.po | 8 | ||||
| -rw-r--r-- | recorder.c | 4 | ||||
| -rw-r--r-- | recording.c | 150 | ||||
| -rw-r--r-- | recording.h | 5 | ||||
| -rw-r--r-- | remux.c | 286 | ||||
| -rw-r--r-- | remux.h | 20 | ||||
| -rw-r--r-- | ringbuffer.c | 45 | ||||
| -rw-r--r-- | ringbuffer.h | 4 | 
33 files changed, 558 insertions, 167 deletions
| @@ -6157,7 +6157,7 @@ Video Disk Recorder Revision History    Reinhard Nissl).  - Implemented full handling of subtitling descriptors (thanks to Mikko Tuumanen). -2009-11-15: Version 1.7.10 +2009-11-22: Version 1.7.10  - Updated the Italian OSD texts (thanks to Diego Pierotto).  - Fixed wrong bracketing in cChannel::SubtitlingType() etc. @@ -6180,3 +6180,11 @@ Video Disk Recorder Revision History  - Fixed EntriesOnSameFileSystem() to avoid using f_fsid, which may be 0 (thanks    to Frank Schmirler).  - Fixed starting a recording at an I-frame. +- Fixed generating the index for recordings from channels that put a whole +  GOP into one payload unit. +- The index file for TS recordings is now regenerated on-the-fly if a +  recording is replayed that has no index. This can also be used to +  re-create a broken index file by manually deleting the index file and then +  replaying the recording (at least until the index file has been generated). +- The cRingBufferLinear::Read() function now returns -1 and sets errno to +  EAGAIN if the buffer is already full. diff --git a/po/ca_ES.po b/po/ca_ES.po index b26e23e1..8915752e 100644 --- a/po/ca_ES.po +++ b/po/ca_ES.po @@ -10,7 +10,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.6.0\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-05-21 13:18+0200\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2008-03-02 19:02+0100\n"  "Last-Translator: Luca Olivetti <luca@ventoso.org>\n"  "Language-Team: Catalanian\n" @@ -927,6 +927,12 @@ msgstr "Canal bloquejat (gravant)!"  msgid "Low disk space!"  msgstr "Disc gaireb ple!" +msgid "Regenerating index file" +msgstr "" + +msgid "Index file regeneration complete" +msgstr "" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "No puc apagar, falta la opci -s !" diff --git a/po/cs_CZ.po b/po/cs_CZ.po index 054cd2b4..b32c293e 100644 --- a/po/cs_CZ.po +++ b/po/cs_CZ.po @@ -8,7 +8,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.6.0\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-05-21 13:18+0200\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2008-02-28 15:00+0200\n"  "Last-Translator: Vladimr Brta <vladimir.barta@k2atmitec.cz>, Ji Dobr <jdobry@centrum.cz>\n"  "Language-Team: Czech\n" @@ -925,6 +925,12 @@ msgstr "Kanl je blokovan (nahrv se)!"  msgid "Low disk space!"  msgstr "Disk bude brzy zaplnn!" +msgid "Regenerating index file" +msgstr "" + +msgid "Index file regeneration complete" +msgstr "" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "Vypnut nen mon - chyb volba '-s'!" diff --git a/po/da_DK.po b/po/da_DK.po index 7c1a1d79..5bcf7769 100644 --- a/po/da_DK.po +++ b/po/da_DK.po @@ -7,7 +7,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.6.0\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-05-21 13:18+0200\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2007-08-12 14:17+0200\n"  "Last-Translator: Mogens Elneff <mogens@elneff.dk>\n"  "Language-Team: Danish\n" @@ -924,6 +924,12 @@ msgstr "Kanal blokeret (optagelse i gang)"  msgid "Low disk space!"  msgstr "Kun lidt diskplads tilbage!" +msgid "Regenerating index file" +msgstr "" + +msgid "Index file regeneration complete" +msgstr "" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "Kan ikke slukke - parameter '-s' ikke angivet!" diff --git a/po/de_DE.po b/po/de_DE.po index 67ecae2b..c6c875dd 100644 --- a/po/de_DE.po +++ b/po/de_DE.po @@ -7,7 +7,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.6.0\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-05-21 13:18+0200\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2007-11-25 15:19+0200\n"  "Last-Translator: Klaus Schmidinger <kls@tvdr.de>\n"  "Language-Team: German\n" @@ -924,6 +924,12 @@ msgstr "Kanal blockiert (zeichnet auf)!"  msgid "Low disk space!"  msgstr "Platte beinahe voll!" +msgid "Regenerating index file" +msgstr "Index-Datei wird regeneriert" + +msgid "Index file regeneration complete" +msgstr "Regenerierung der Index-Datei abgeschlossen" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "Ausschalten unmglich - Option '-s' fehlt!" diff --git a/po/el_GR.po b/po/el_GR.po index b9b59eae..c89b6897 100644 --- a/po/el_GR.po +++ b/po/el_GR.po @@ -7,7 +7,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.6.0\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-05-21 13:18+0200\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2007-08-12 14:17+0200\n"  "Last-Translator: Dimitrios Dimitrakos <mail@dimitrios.de>\n"  "Language-Team: Greek\n" @@ -924,6 +924,12 @@ msgstr "    ( )!"  msgid "Low disk space!"  msgstr "    !" +msgid "Regenerating index file" +msgstr "" + +msgid "Index file regeneration complete" +msgstr "" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "   .    '-s'!" diff --git a/po/es_ES.po b/po/es_ES.po index f3f515a0..6cc9cee6 100644 --- a/po/es_ES.po +++ b/po/es_ES.po @@ -8,7 +8,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.6.0\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-05-21 13:18+0200\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2008-03-02 19:02+0100\n"  "Last-Translator: Luca Olivetti <luca@ventoso.org>\n"  "Language-Team: Spanish\n" @@ -925,6 +925,12 @@ msgstr "Canal bloqueado (grabando)!"  msgid "Low disk space!"  msgstr "Poco espacio en disco!" +msgid "Regenerating index file" +msgstr "" + +msgid "Index file regeneration complete" +msgstr "" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "No se puede apagar - falta el parmetro '-s'!" diff --git a/po/et_EE.po b/po/et_EE.po index 220857df..2823c742 100644 --- a/po/et_EE.po +++ b/po/et_EE.po @@ -7,7 +7,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.6.0\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-05-21 13:18+0200\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2007-08-12 14:17+0200\n"  "Last-Translator: Arthur Konovalov <kasjas@hot.ee>\n"  "Language-Team: Estonian\n" @@ -924,6 +924,12 @@ msgstr "Kanal lukus (salvestamine aktiivne)!"  msgid "Low disk space!"  msgstr "Kvaketas tis!" +msgid "Regenerating index file" +msgstr "" + +msgid "Index file regeneration complete" +msgstr "" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "Vljallitamine ebannestus - '-s' parameeter puudub!" diff --git a/po/fi_FI.po b/po/fi_FI.po index a51580cc..9718e53f 100644 --- a/po/fi_FI.po +++ b/po/fi_FI.po @@ -10,7 +10,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.6.0\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-05-21 13:18+0200\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2007-08-15 15:52+0200\n"  "Last-Translator: Rolf Ahrenberg <rahrenbe@cc.hut.fi>\n"  "Language-Team: Finnish\n" @@ -927,6 +927,12 @@ msgstr "Kanava lukittu (tallennus kynniss)!"  msgid "Low disk space!"  msgstr "Tallennustila loppumassa!" +msgid "Regenerating index file" +msgstr "" + +msgid "Index file regeneration complete" +msgstr "" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "Sammutus ei onnistu - '-s' parametri puuttuu!" diff --git a/po/fr_FR.po b/po/fr_FR.po index 0877c449..8f6778a6 100644 --- a/po/fr_FR.po +++ b/po/fr_FR.po @@ -13,7 +13,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.6.0\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-05-21 13:18+0200\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2008-02-27 18:14+0100\n"  "Last-Translator: Jean-Claude Repetto <jc@repetto.org>\n"  "Language-Team: French\n" @@ -930,6 +930,12 @@ msgstr "Chane verrouille (enregistrement en cours) !"  msgid "Low disk space!"  msgstr "Disque presque plein !" +msgid "Regenerating index file" +msgstr "" + +msgid "Index file regeneration complete" +msgstr "" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "Arrt impossible - option '-s' absente !" diff --git a/po/hr_HR.po b/po/hr_HR.po index fffe8085..32976b85 100644 --- a/po/hr_HR.po +++ b/po/hr_HR.po @@ -9,7 +9,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.6.0\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-05-21 13:18+0200\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2008-03-17 19:00+0100\n"  "Last-Translator: Adrian Caval <anrxc@sysphere.org>\n"  "Language-Team: Croatian\n" @@ -926,6 +926,12 @@ msgstr "Program zakljuan (snimanje)!"  msgid "Low disk space!"  msgstr "Malo prostora na disku!" +msgid "Regenerating index file" +msgstr "" + +msgid "Index file regeneration complete" +msgstr "" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "Gaenje nemogue - nedostaje opcija '-s'!" diff --git a/po/hu_HU.po b/po/hu_HU.po index 4945d7f0..e3d2b70d 100644 --- a/po/hu_HU.po +++ b/po/hu_HU.po @@ -10,7 +10,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.6.0\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-05-21 13:18+0200\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2007-12-01 21:42+0200\n"  "Last-Translator: Istvn Fley <ifuley@tigercomp.ro>\n"  "Language-Team: Hungarian\n" @@ -927,6 +927,12 @@ msgstr "Az ad blokkolva (felvtel)!"  msgid "Low disk space!"  msgstr "A merev lemez majdnem tele!" +msgid "Regenerating index file" +msgstr "" + +msgid "Index file regeneration complete" +msgstr "" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "A lellts nem lehetsges - Opci '-s' hinyzik!" diff --git a/po/it_IT.po b/po/it_IT.po index dc8919c4..9032a7c8 100644 --- a/po/it_IT.po +++ b/po/it_IT.po @@ -11,7 +11,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.6.0\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-05-21 13:18+0200\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2009-08-29 11:16+0100\n"  "Last-Translator: Diego Pierotto <vdr-italian@tiscali.it>\n"  "Language-Team: Italian\n" @@ -931,6 +931,12 @@ msgstr "Canale bloccato (in registrazione)!"  msgid "Low disk space!"  msgstr "Poco spazio su disco!" +msgid "Regenerating index file" +msgstr "" + +msgid "Index file regeneration complete" +msgstr "" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "Impossibile spegnere - parametro '-s' non assegnato!" diff --git a/po/lt_LT.po b/po/lt_LT.po index 5404f7e7..c50a74b6 100644 --- a/po/lt_LT.po +++ b/po/lt_LT.po @@ -7,7 +7,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.7.9\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-08-27 22:29+0300\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2009-10-17 14:19+0200\n"  "Last-Translator: Valdemaras Pipiras <varas@ambernet.lt>\n"  "Language-Team: Lithuanian\n" @@ -924,6 +924,12 @@ msgstr "Kanalas užblokuotas (įrašinėjama)!"  msgid "Low disk space!"  msgstr "Mažai vietos diske!" +msgid "Regenerating index file" +msgstr "" + +msgid "Index file regeneration complete" +msgstr "" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "Sistemos negalima išjungti, nes starto metu nebuvo komandinėj eilutėj paduota savybė '-s'!" diff --git a/po/nl_NL.po b/po/nl_NL.po index 5fd84596..99a8f450 100644 --- a/po/nl_NL.po +++ b/po/nl_NL.po @@ -11,7 +11,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.6.0\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-05-21 13:18+0200\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2008-02-26 17:20+0100\n"  "Last-Translator: Johan Schuring <johan.schuring@vetteblei.nl>\n"  "Language-Team: Dutch\n" @@ -928,6 +928,12 @@ msgstr "Kanaal geblokkeerd (neemt op)!"  msgid "Low disk space!"  msgstr "Hardeschijf bijna vol!" +msgid "Regenerating index file" +msgstr "" + +msgid "Index file regeneration complete" +msgstr "" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "Shutdown onmogelijk - Optie '-s' ontbreekt!" diff --git a/po/nn_NO.po b/po/nn_NO.po index 09513be8..070e974b 100644 --- a/po/nn_NO.po +++ b/po/nn_NO.po @@ -8,7 +8,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.6.0\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-05-21 13:18+0200\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2007-08-12 14:17+0200\n"  "Last-Translator: Truls Slevigen <truls@slevigen.no>\n"  "Language-Team: Norwegian\n" @@ -925,6 +925,12 @@ msgstr "Kanalen er lst (opptak)!"  msgid "Low disk space!"  msgstr "Lite ledig diskplass!" +msgid "Regenerating index file" +msgstr "" + +msgid "Index file regeneration complete" +msgstr "" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "Kan ikke sl av - startet uten parameteret '-s'!" diff --git a/po/pl_PL.po b/po/pl_PL.po index 99dd6dc0..daca48f4 100644 --- a/po/pl_PL.po +++ b/po/pl_PL.po @@ -8,7 +8,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.6.0\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-05-21 13:18+0200\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2008-03-09 12:59+0100\n"  "Last-Translator: Michael Rakowski <mrak@gmx.de>\n"  "Language-Team:  Polish\n" @@ -925,6 +925,12 @@ msgstr "Kana zablokowany (trwa nagrywanie)!"  msgid "Low disk space!"  msgstr "Mao miejsca na dysku!" +msgid "Regenerating index file" +msgstr "" + +msgid "Index file regeneration complete" +msgstr "" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "Nie mona wyczy - nie podano opcji '-s'!" diff --git a/po/pt_PT.po b/po/pt_PT.po index a01d020f..cee93d7c 100644 --- a/po/pt_PT.po +++ b/po/pt_PT.po @@ -7,7 +7,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.6.0\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-05-21 13:18+0200\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2008-03-18 17:04+0100\n"  "Last-Translator: anonymous\n"  "Language-Team: Portuguese\n" @@ -924,6 +924,12 @@ msgstr "Canal bloqueado (a gravar)!"  msgid "Low disk space!"  msgstr "Espao em disco reduzido!" +msgid "Regenerating index file" +msgstr "" + +msgid "Index file regeneration complete" +msgstr "" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "Impossvel desligar - falta a opo '-s'!" diff --git a/po/ro_RO.po b/po/ro_RO.po index aaf5e2b2..6059aa58 100644 --- a/po/ro_RO.po +++ b/po/ro_RO.po @@ -8,7 +8,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.6.0\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-05-21 13:18+0200\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2008-02-25 00:39+0100\n"  "Last-Translator: Lucian Muresan <lucianm@users.sourceforge.net>\n"  "Language-Team: Romanian\n" @@ -927,6 +927,12 @@ msgstr "Canal blocat (nregistrare)!"  msgid "Low disk space!"  msgstr "Spaiul pe disc e foarte sczut!" +msgid "Regenerating index file" +msgstr "" + +msgid "Index file regeneration complete" +msgstr "" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "Nu pot nchide - vezi opiunea '-s'" diff --git a/po/ru_RU.po b/po/ru_RU.po index 9e73d416..3de70437 100644 --- a/po/ru_RU.po +++ b/po/ru_RU.po @@ -8,7 +8,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.6.0\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-05-21 13:18+0200\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2008-12-15 14:37+0100\n"  "Last-Translator: Oleg Roitburd <oleg@roitburd.de>\n"  "Language-Team: Russian\n" @@ -925,6 +925,12 @@ msgstr "  ( )!"  msgid "Low disk space!"  msgstr "   !" +msgid "Regenerating index file" +msgstr "" + +msgid "Index file regeneration complete" +msgstr "" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "  -    '-s'!" diff --git a/po/sk_SK.po b/po/sk_SK.po index e6375df0..8471140d 100644 --- a/po/sk_SK.po +++ b/po/sk_SK.po @@ -8,7 +8,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.6.0\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-05-21 13:18+0200\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2009-09-30 12:50+0100\n"  "Last-Translator: Milan Hrala <hrala.milan@gmail.com>\n"  "Language-Team: Slovak\n" @@ -925,6 +925,12 @@ msgstr "Kanl je zamknut (nahrva sa)!"  msgid "Low disk space!"  msgstr "Za chvku bude pln disk!" +msgid "Regenerating index file" +msgstr "" + +msgid "Index file regeneration complete" +msgstr "" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "Vypnutie nie je mon - chba voba '-s'!" @@ -1023,4 +1029,3 @@ msgstr "ktorkovek  klvesa zru retart"  #, c-format  msgid "VDR will shut down in %s minutes"  msgstr "VDR sa vypne za %s mint" - diff --git a/po/sl_SI.po b/po/sl_SI.po index 58316151..4f89ff77 100644 --- a/po/sl_SI.po +++ b/po/sl_SI.po @@ -8,7 +8,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.6.0\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-05-21 13:18+0200\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2008-02-28 19:44+0100\n"  "Last-Translator: Matjaz Thaler <matjaz.thaler@guest.arnes.si>\n"  "Language-Team: Slovenian\n" @@ -925,6 +925,12 @@ msgstr "Zaklenjen kanal (snemanje)!"  msgid "Low disk space!"  msgstr "Premalo prostora na disku!" +msgid "Regenerating index file" +msgstr "" + +msgid "Index file regeneration complete" +msgstr "" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "Zaustavitev ni izvedljiva - opcija '-s' ni podana!" diff --git a/po/sv_SE.po b/po/sv_SE.po index 5fbefa8e..d368bb65 100644 --- a/po/sv_SE.po +++ b/po/sv_SE.po @@ -10,7 +10,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.6.0\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-05-21 13:18+0200\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2008-03-12 18:25+0100\n"  "Last-Translator: Magnus Andersson <svankan@bahnhof.se>\n"  "Language-Team: Swedish\n" @@ -927,6 +927,12 @@ msgstr "Kanalen r lst (inspelning pgr)!"  msgid "Low disk space!"  msgstr "Lgt diskutrymme!" +msgid "Regenerating index file" +msgstr "" + +msgid "Index file regeneration complete" +msgstr "" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "Kan inte avsluta, mste anvnda parameter '-s'" diff --git a/po/tr_TR.po b/po/tr_TR.po index c6f38df9..39138d59 100644 --- a/po/tr_TR.po +++ b/po/tr_TR.po @@ -7,7 +7,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.6.0\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-05-21 13:18+0200\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2008-02-28 00:33+0100\n"  "Last-Translator: Oktay Yolgeen <oktay_73@yahoo.de>\n"  "Language-Team: Turkish\n" @@ -924,6 +924,12 @@ msgstr "Kanal geersiz (kayt ediliyor)!"  msgid "Low disk space!"  msgstr "Kayt kapasitesi az!" +msgid "Regenerating index file" +msgstr "" + +msgid "Index file regeneration complete" +msgstr "" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "Kapatlamyor - '-s' seenei verilmemi!" diff --git a/po/uk_UA.po b/po/uk_UA.po index c35b24fc..6c2f58ab 100644 --- a/po/uk_UA.po +++ b/po/uk_UA.po @@ -7,7 +7,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.7.7\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-05-31 11:11+0200\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2009-05-31 13:17+0200\n"  "Last-Translator: Yarema aka Knedlyk <yupadmin@gmail.com>\n"  "Language-Team: Ukrainian\n" @@ -924,6 +924,12 @@ msgstr "Канал заблоковано (йде запис)!"  msgid "Low disk space!"  msgstr "Недостатньо місця на диску!" +msgid "Regenerating index file" +msgstr "" + +msgid "Index file regeneration complete" +msgstr "" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "Виключенння неможливе - не задано параметр '-s'!" diff --git a/po/zh_CN.po b/po/zh_CN.po index 5291adb0..03bddab9 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -7,7 +7,7 @@ msgid ""  msgstr ""  "Project-Id-Version: VDR 1.6.0\n"  "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" -"POT-Creation-Date: 2009-02-09 12:37+0800\n" +"POT-Creation-Date: 2009-11-22 12:28+0100\n"  "PO-Revision-Date: 2009-09-23 23:50+0800\n"  "Last-Translator: Nan Feng <nfgx@21cn.com>\n"  "Language-Team: Chinese\n" @@ -927,6 +927,12 @@ msgstr "频道已经锁定 (录像)!"  msgid "Low disk space!"  msgstr "磁盘空间不足!" +msgid "Regenerating index file" +msgstr "" + +msgid "Index file regeneration complete" +msgstr "" +  msgid "Can't shutdown - option '-s' not given!"  msgstr "不能关机 - 操作 '-s' 不允许!" @@ -4,7 +4,7 @@   * See the main source file 'vdr.c' for copyright information and   * how to reach the author.   * - * $Id: recorder.c 2.5 2009/11/15 15:27:08 kls Exp $ + * $Id: recorder.c 2.6 2009/11/21 15:58:12 kls Exp $   */  #include "recorder.h" @@ -30,7 +30,7 @@ cRecorder::cRecorder(const char *FileName, tChannelID ChannelID, int Priority, i    SpinUpDisk(FileName); -  ringBuffer = new cRingBufferLinear(RECORDERBUFSIZE, TS_SIZE * 2, true, "Recorder"); +  ringBuffer = new cRingBufferLinear(RECORDERBUFSIZE, MIN_TS_PACKETS_FOR_FRAME_DETECTOR * TS_SIZE, true, "Recorder");    ringBuffer->SetTimeouts(0, 100);    cChannel *Channel = Channels.GetByChannelID(ChannelID);    int Pid = VPid; diff --git a/recording.c b/recording.c index f3c2c5ab..ab94c32a 100644 --- a/recording.c +++ b/recording.c @@ -4,7 +4,7 @@   * See the main source file 'vdr.c' for copyright information and   * how to reach the author.   * - * $Id: recording.c 2.17 2009/08/16 10:39:43 kls Exp $ + * $Id: recording.c 2.18 2009/11/22 11:20:53 kls Exp $   */  #include "recording.h" @@ -21,6 +21,7 @@  #include "i18n.h"  #include "interface.h"  #include "remux.h" +#include "ringbuffer.h"  #include "skins.h"  #include "tools.h"  #include "videodir.h" @@ -1309,6 +1310,124 @@ void cRecordingUserCommand::InvokeCommand(const char *State, const char *Recordi       }  } +// --- cIndexFileGenerator --------------------------------------------------- + +#define IFG_BUFFER_SIZE KILOBYTE(100) + +class cIndexFileGenerator : public cThread { +private: +  cString recordingName; +protected: +  virtual void Action(void); +public: +  cIndexFileGenerator(const char *RecordingName); +  ~cIndexFileGenerator(); +  }; + +cIndexFileGenerator::cIndexFileGenerator(const char *RecordingName) +:cThread("index file generator") +,recordingName(RecordingName) +{ +  Start(); +} + +cIndexFileGenerator::~cIndexFileGenerator() +{ +  Cancel(3); +} + +void cIndexFileGenerator::Action(void) +{ +  bool IndexFileComplete = false; +  bool Rewind = false; +  cFileName FileName(recordingName, false); +  cUnbufferedFile *ReplayFile = FileName.Open(); +  cRingBufferLinear Buffer(IFG_BUFFER_SIZE, MIN_TS_PACKETS_FOR_FRAME_DETECTOR * TS_SIZE); +  cPatPmtParser PatPmtParser; +  cFrameDetector FrameDetector; +  cIndexFile IndexFile(recordingName, true); +  int BufferChunks = KILOBYTE(1); // no need to read a lot at the beginning when parsing PAT/PMT +  off_t FileSize = 0; +  off_t FrameOffset = -1; +  Skins.QueueMessage(mtInfo, tr("Regenerating index file")); +  while (Running()) { +        // Rewind input file: +        if (Rewind) { +           ReplayFile = FileName.SetOffset(1); +           Buffer.Clear(); +           Rewind = false; +           } +        // Process data: +        int Length; +        uchar *Data = Buffer.Get(Length); +        if (Data) { +           if (FrameDetector.Synced()) { +              // Step 3 - generate the index: +              if (TsPid(Data) == PATPID) +                 FrameOffset = FileSize; // the PAT/PMT is at the beginning of an I-frame +              int Processed = FrameDetector.Analyze(Data, Length); +              if (Processed > 0) { +                 if (FrameDetector.NewFrame()) { +                    IndexFile.Write(FrameDetector.IndependentFrame(), FileName.Number(), FrameOffset >= 0 ? FrameOffset : FileSize); +                    FrameOffset = -1; +                    } +                 FileSize += Processed; +                 Buffer.Del(Processed); +                 } +              } +           else if (PatPmtParser.Vpid()) { +              // Step 2 - sync FrameDetector: +              int Processed = FrameDetector.Analyze(Data, Length); +              if (Processed > 0) { +                 if (FrameDetector.Synced()) { +                    // Synced FrameDetector, so rewind for actual processing: +                    FrameDetector.Reset(); +                    Rewind = true; +                    } +                 Buffer.Del(Processed); +                 } +              } +           else { +              // Step 1 - parse PAT/PMT: +              uchar *p = Data; +              while (Length >= TS_SIZE) { +                    int Pid = TsPid(p); +                    if (Pid == 0) +                       PatPmtParser.ParsePat(p, TS_SIZE); +                    else if (Pid == PatPmtParser.PmtPid()) +                       PatPmtParser.ParsePmt(p, TS_SIZE); +                    Length -= TS_SIZE; +                    p += TS_SIZE; +                    if (PatPmtParser.Vpid()) { +                       // Found Vpid, so rewind to sync FrameDetector: +                       FrameDetector.SetPid(PatPmtParser.Vpid(), PatPmtParser.Vtype()); +                       BufferChunks = IFG_BUFFER_SIZE; +                       Rewind = true; +                       break; +                       } +                    } +              Buffer.Del(p - Data); +              } +           } +        // Read data: +        else if (ReplayFile) { +           int Result = Buffer.Read(ReplayFile, BufferChunks); +           if (Result == 0) // EOF +              ReplayFile = FileName.NextFile(); +           } +        // Recording has been processed: +        else { +           IndexFileComplete = true; +           break; +           } +        } +  // Delete the index file if the recording has not been processed entirely: +  if (IndexFileComplete) +     Skins.QueueMessage(mtInfo, tr("Index file regeneration complete")); +  else +     IndexFile.Delete(); +} +  // --- cIndexFile ------------------------------------------------------------  #define INDEXFILESUFFIX     "/index" @@ -1343,6 +1462,9 @@ struct tIndexTs {    }    }; +#define MAXWAITFORINDEXFILE     10 // max. time to wait for the regenerated index file (seconds) +#define INDEXFILECHECKINTERVAL 500 // ms between checks for existence of the regenerated index file +  cIndexFile::cIndexFile(const char *FileName, bool Record, bool IsPesRecording)  :resumeFile(FileName, IsPesRecording)  { @@ -1352,6 +1474,7 @@ cIndexFile::cIndexFile(const char *FileName, bool Record, bool IsPesRecording)    last = -1;    index = NULL;    isPesRecording = IsPesRecording; +  indexFileGenerator = NULL;    if (FileName) {       const char *Suffix = isPesRecording ? INDEXFILESUFFIX ".vdr" : INDEXFILESUFFIX;       fileName = MALLOC(char, strlen(FileName) + strlen(Suffix) + 1); @@ -1360,6 +1483,18 @@ cIndexFile::cIndexFile(const char *FileName, bool Record, bool IsPesRecording)          char *pFileExt = fileName + strlen(fileName);          strcpy(pFileExt, Suffix);          int delta = 0; +        if (!Record && access(fileName, R_OK) != 0) { +           // Index file doesn't exist, so try to regenerate it: +           if (!isPesRecording) { // sorry, can only do this for TS recordings +              resumeFile.Delete(); // just in case +              indexFileGenerator = new cIndexFileGenerator(FileName); +              // Wait until the index file exists: +              time_t tmax = time(NULL) + MAXWAITFORINDEXFILE; +              do { +                 cCondWait::SleepMs(INDEXFILECHECKINTERVAL); // start with a sleep, to give it a head start +                 } while (access(fileName, R_OK) != 0 && time(NULL) < tmax); +              } +           }          if (access(fileName, R_OK) == 0) {             struct stat buf;             if (stat(fileName, &buf) == 0) { @@ -1421,6 +1556,7 @@ cIndexFile::~cIndexFile()       close(f);    free(fileName);    free(index); +  delete indexFileGenerator;  }  void cIndexFile::ConvertFromPes(tIndexTs *IndexTs, int Count) @@ -1598,6 +1734,18 @@ bool cIndexFile::IsStillRecording()    return f >= 0;  } +void cIndexFile::Delete(void) +{ +  if (fileName) { +     dsyslog("deleting index file '%s'", fileName); +     if (f >= 0) { +        close(f); +        f = -1; +        } +     unlink(fileName); +     } +} +  // --- cFileName -------------------------------------------------------------  #define MAXFILESPERRECORDINGPES 255 diff --git a/recording.h b/recording.h index a895a2d3..bc3479fe 100644 --- a/recording.h +++ b/recording.h @@ -4,7 +4,7 @@   * See the main source file 'vdr.c' for copyright information and   * how to reach the author.   * - * $Id: recording.h 2.9 2009/08/16 10:45:00 kls Exp $ + * $Id: recording.h 2.10 2009/11/21 16:12:55 kls Exp $   */  #ifndef __RECORDING_H @@ -220,6 +220,7 @@ public:  #define MAXVIDEOFILESIZEDEFAULT MAXVIDEOFILESIZEPES  struct tIndexTs; +class cIndexFileGenerator;  class cIndexFile {  private: @@ -229,6 +230,7 @@ private:    tIndexTs *index;    bool isPesRecording;    cResumeFile resumeFile; +  cIndexFileGenerator *indexFileGenerator;    cMutex mutex;    void ConvertFromPes(tIndexTs *IndexTs, int Count);    void ConvertToPes(tIndexTs *IndexTs, int Count); @@ -245,6 +247,7 @@ public:    int GetResume(void) { return resumeFile.Read(); }    bool StoreResume(int Index) { return resumeFile.Save(Index); }    bool IsStillRecording(void); +  void Delete(void);    };  class cFileName { @@ -4,7 +4,7 @@   * See the main source file 'vdr.c' for copyright information and   * how to reach the author.   * - * $Id: remux.c 2.28 2009/11/01 15:33:32 kls Exp $ + * $Id: remux.c 2.29 2009/11/22 11:23:27 kls Exp $   */  #include "remux.h" @@ -264,8 +264,8 @@ void cPatPmtGenerator::GeneratePat(void)    uchar *p = pat;    int i = 0;    p[i++] = TS_SYNC_BYTE; // TS indicator -  p[i++] = TS_PAYLOAD_START; // flags (3), pid hi (5) -  p[i++] = 0x00; // pid lo +  p[i++] = TS_PAYLOAD_START | (PATPID >> 8); // flags (3), pid hi (5) +  p[i++] = PATPID & 0xFF; // pid lo    p[i++] = 0x10; // flags (4), continuity counter (4)    p[i++] = 0x00; // pointer field (payload unit start indicator is set)    int PayloadStart = i; @@ -733,20 +733,20 @@ void PesDump(const char *Name, const u_char *Data, int Length)  // --- cFrameDetector -------------------------------------------------------- +#define EMPTY_SCANNER (0xFFFFFFFF) +  cFrameDetector::cFrameDetector(int Pid, int Type)  { -  pid = Pid; -  type = Type; +  SetPid(Pid, Type);    synced = false;    newFrame = independentFrame = false;    numPtsValues = 0;    numIFrames = 0; -  isVideo = type == 0x01 || type == 0x02 || type == 0x1B; // MPEG 1, 2 or 4    frameDuration = 0;    framesInPayloadUnit = framesPerPayloadUnit = 0;    payloadUnitOfFrame = 0;    scanning = false; -  scanner = 0; +  scanner = EMPTY_SCANNER;  }  static int CmpUint32(const void *p1, const void *p2) @@ -756,8 +756,24 @@ static int CmpUint32(const void *p1, const void *p2)    return 0;  } +void cFrameDetector::SetPid(int Pid, int Type) +{ +  pid = Pid; +  type = Type; +  isVideo = type == 0x01 || type == 0x02 || type == 0x1B; // MPEG 1, 2 or 4 +} + +void cFrameDetector::Reset(void) +{ +  newFrame = independentFrame = false; +  payloadUnitOfFrame = 0; +  scanning = false; +  scanner = EMPTY_SCANNER; +} +  int cFrameDetector::Analyze(const uchar *Data, int Length)  { +  int SeenPayloadStart = false;    int Processed = 0;    newFrame = independentFrame = false;    while (Length >= TS_SIZE) { @@ -768,144 +784,156 @@ int cFrameDetector::Analyze(const uchar *Data, int Length)             esyslog("ERROR: skipped %d bytes to sync on start of TS packet", Skipped);             return Processed + Skipped;             } -        if (TsHasPayload(Data) && !TsIsScrambled(Data) && TsPid(Data) == pid) { -           if (TsPayloadStart(Data)) { -              if (synced && Processed) -                 return Processed; -              if (Length < 2 * TS_SIZE) -                 return 0; // need more data, in case the frame type is stored in the second TS packet -              if (!frameDuration) { -                 // frame duration unknown, so collect a sequence of PTS values: -                 if (numPtsValues < MaxPtsValues && numIFrames < 2) { // collect a sequence containing at least two I-frames -                    const uchar *Pes = Data + TsPayloadOffset(Data); -                    if (PesHasPts(Pes)) { -                       ptsValues[numPtsValues] = PesGetPts(Pes); -                       // check for rollover: -                       if (numPtsValues && ptsValues[numPtsValues - 1] > 0xF0000000 && ptsValues[numPtsValues] < 0x10000000) { -                          dbgframes("#"); -                          numPtsValues = 0; -                          numIFrames = 0; +        if (TsHasPayload(Data) && !TsIsScrambled(Data)) { +           int Pid = TsPid(Data); +           if (Pid == pid) { +              if (TsPayloadStart(Data)) { +                 SeenPayloadStart = true; +                 if (synced && Processed) +                    return Processed; +                 if (Length < MIN_TS_PACKETS_FOR_FRAME_DETECTOR * TS_SIZE) +                    return 0; // need more data, in case the frame type is not stored in the first TS packet +                 if (!frameDuration) { +                    // frame duration unknown, so collect a sequence of PTS values: +                    if (numPtsValues < MaxPtsValues && numIFrames < 2) { // collect a sequence containing at least two I-frames +                       const uchar *Pes = Data + TsPayloadOffset(Data); +                       if (PesHasPts(Pes)) { +                          ptsValues[numPtsValues] = PesGetPts(Pes); +                          // check for rollover: +                          if (numPtsValues && ptsValues[numPtsValues - 1] > 0xF0000000 && ptsValues[numPtsValues] < 0x10000000) { +                             dbgframes("#"); +                             numPtsValues = 0; +                             numIFrames = 0; +                             } +                          else +                             numPtsValues++;                            } -                       else -                          numPtsValues++;                         } -                    } -                 else { -                    // find the smallest PTS delta: -                    qsort(ptsValues, numPtsValues, sizeof(uint32_t), CmpUint32); -                    numPtsValues--; -                    for (int i = 0; i < numPtsValues; i++) -                        ptsValues[i] = ptsValues[i + 1] - ptsValues[i]; -                    qsort(ptsValues, numPtsValues, sizeof(uint32_t), CmpUint32); -                    uint32_t Delta = ptsValues[0]; -                    // determine frame info: -                    if (isVideo) { -                       if (Delta % 3600 == 0) -                          frameDuration = 3600; // PAL, 25 fps -                       else if (Delta % 3003 == 0) -                          frameDuration = 3003; // NTSC, 29.97 fps -                       else if (Delta == 1800) { -                          frameDuration = 3600; // PAL, 25 fps -                          framesPerPayloadUnit = -2; -                          } -                       else if (Delta == 1501) { -                          frameDuration = 3003; // NTSC, 29.97 fps -                          framesPerPayloadUnit = -2; -                          } -                       else { -                          frameDuration = 3600; // unknown, assuming 25 fps -                          dsyslog("unknown frame duration (%d), assuming 25 fps", Delta); +                    else { +                       // find the smallest PTS delta: +                       qsort(ptsValues, numPtsValues, sizeof(uint32_t), CmpUint32); +                       numPtsValues--; +                       for (int i = 0; i < numPtsValues; i++) +                           ptsValues[i] = ptsValues[i + 1] - ptsValues[i]; +                       qsort(ptsValues, numPtsValues, sizeof(uint32_t), CmpUint32); +                       uint32_t Delta = ptsValues[0]; +                       // determine frame info: +                       if (isVideo) { +                          if (Delta % 3600 == 0) +                             frameDuration = 3600; // PAL, 25 fps +                          else if (Delta % 3003 == 0) +                             frameDuration = 3003; // NTSC, 29.97 fps +                          else if (Delta == 1800) { +                             frameDuration = 3600; // PAL, 25 fps +                             framesPerPayloadUnit = -2; +                             } +                          else if (Delta == 1501) { +                             frameDuration = 3003; // NTSC, 29.97 fps +                             framesPerPayloadUnit = -2; +                             } +                          else { +                             frameDuration = 3600; // unknown, assuming 25 fps +                             dsyslog("unknown frame duration (%d), assuming 25 fps", Delta); +                             }                            } +                       else // audio +                          frameDuration = Delta; // PTS of audio frames is always increasing +                       dbgframes("\nframe duration = %d  FPS = %5.2f  FPPU = %d\n", frameDuration, 90000.0 / frameDuration, framesPerPayloadUnit);                         } -                    else // audio -                       frameDuration = Delta; // PTS of audio frames is always increasing -                    dbgframes("\nframe duration = %d  FPS = %5.2f  FPPU = %d\n", frameDuration, 90000.0 / frameDuration, framesPerPayloadUnit);                      } +                 scanner = EMPTY_SCANNER; +                 scanning = true;                   } -              scanner = 0; -              scanning = true; -              } -           if (scanning) { -              int PayloadOffset = TsPayloadOffset(Data); -              if (TsPayloadStart(Data)) { -                 PayloadOffset += PesPayloadOffset(Data + PayloadOffset); -                 if (!framesPerPayloadUnit) -                    framesPerPayloadUnit = framesInPayloadUnit; -                 if (DebugFrames && !synced) -                    dbgframes("/"); -                 } -              for (int i = PayloadOffset; scanning && i < TS_SIZE; i++) { -                  scanner <<= 8; -                  scanner |= Data[i]; -                  switch (type) { -                    case 0x01: // MPEG 1 video -                    case 0x02: // MPEG 2 video -                         if (scanner == 0x00000100) { // Picture Start Code -                            newFrame = true; -                            independentFrame = ((Data[i + 2] >> 3) & 0x07) == 1; // I-Frame -                            if (synced) { -                               if (framesPerPayloadUnit <= 1) -                                  scanning = false; +              if (scanning) { +                 int PayloadOffset = TsPayloadOffset(Data); +                 if (TsPayloadStart(Data)) { +                    PayloadOffset += PesPayloadOffset(Data + PayloadOffset); +                    if (!framesPerPayloadUnit) +                       framesPerPayloadUnit = framesInPayloadUnit; +                    if (DebugFrames && !synced) +                       dbgframes("/"); +                    } +                 for (int i = PayloadOffset; scanning && i < TS_SIZE; i++) { +                     scanner <<= 8; +                     scanner |= Data[i]; +                     switch (type) { +                       case 0x01: // MPEG 1 video +                       case 0x02: // MPEG 2 video +                            if (scanner == 0x00000100) { // Picture Start Code +                               scanner = EMPTY_SCANNER; +                               if (synced && !SeenPayloadStart && Processed) +                                  return Processed; // flush everything before this new frame +                               newFrame = true; +                               independentFrame = ((Data[i + 2] >> 3) & 0x07) == 1; // I-Frame +                               if (synced) { +                                  if (framesPerPayloadUnit <= 1) +                                     scanning = false; +                                  } +                               else { +                                  framesInPayloadUnit++; +                                  if (independentFrame) +                                     numIFrames++; +                                  dbgframes("%d ", (Data[i + 2] >> 3) & 0x07); +                                  } +                               if (synced) +                                  return Processed + TS_SIZE; // flag this new frame                                 } -                            else { -                               framesInPayloadUnit++; -                               if (independentFrame) -                                  numIFrames++; -                               dbgframes("%d ", (Data[i + 2] >> 3) & 0x07); +                            break; +                       case 0x1B: // MPEG 4 video +                            if (scanner == 0x00000109) { // Access Unit Delimiter +                               scanner = EMPTY_SCANNER; +                               if (synced && !SeenPayloadStart && Processed) +                                  return Processed; // flush everything before this new frame +                               newFrame = true; +                               independentFrame = Data[i + 1] == 0x10; +                               if (synced) { +                                  if (framesPerPayloadUnit < 0) { +                                     payloadUnitOfFrame = (payloadUnitOfFrame + 1) % -framesPerPayloadUnit; +                                     if (payloadUnitOfFrame != 0 && independentFrame) +                                        payloadUnitOfFrame = 0; +                                     if (payloadUnitOfFrame) +                                        newFrame = false; +                                     } +                                  if (framesPerPayloadUnit <= 1) +                                     scanning = false; +                                  } +                               else { +                                  framesInPayloadUnit++; +                                  if (independentFrame) +                                     numIFrames++; +                                  dbgframes("%02X ", Data[i + 1]); +                                  } +                               if (synced) +                                  return Processed + TS_SIZE; // flag this new frame                                 } -                            scanner = 0; +                            break; +                       case 0x04: // MPEG audio +                       case 0x06: // AC3 audio                              if (synced && Processed)                                 return Processed; -                            } -                         break; -                    case 0x1B: // MPEG 4 video -                         if (scanner == 0x00000109) { // Access Unit Delimiter                              newFrame = true; -                            independentFrame = Data[i + 1] == 0x10; -                            if (synced) { -                               if (framesPerPayloadUnit < 0) { -                                  payloadUnitOfFrame = (payloadUnitOfFrame + 1) % -framesPerPayloadUnit; -                                  if (payloadUnitOfFrame != 0 && independentFrame) -                                     payloadUnitOfFrame = 0; -                                  if (payloadUnitOfFrame) -                                     newFrame = false; -                                  } -                               if (framesPerPayloadUnit <= 1) -                                  scanning = false; -                               } -                            else { -                               framesInPayloadUnit++; -                               if (independentFrame) +                            independentFrame = true; +                            if (!synced) { +                               framesInPayloadUnit = 1; +                               if (TsPayloadStart(Data))                                    numIFrames++; -                               dbgframes("%02X ", Data[i + 1]);                                 } -                            if (synced && Processed) -                               return Processed; -                            scanner = 0; -                            } -                         break; -                    case 0x04: // MPEG audio -                    case 0x06: // AC3 audio -                         newFrame = true; -                         independentFrame = true; -                         if (!synced) { -                            framesInPayloadUnit = 1; -                            if (TsPayloadStart(Data)) -                               numIFrames++; -                            } -                         scanning = false; -                         if (synced && Processed) -                            return Processed; -                         break; -                    default: esyslog("ERROR: unknown stream type %d (PID %d) in frame detector", type, pid); -                             pid = 0; // let's just ignore any further data +                            scanning = false; +                            break; +                       default: esyslog("ERROR: unknown stream type %d (PID %d) in frame detector", type, pid); +                                pid = 0; // let's just ignore any further data +                       } +                     } +                 if (!synced && frameDuration && independentFrame) { +                    synced = true; +                    dbgframes("*"); +                    Reset(); +                    return Processed + TS_SIZE;                      } -                  } -              if (!synced && frameDuration && independentFrame) { -                 synced = true; -                 dbgframes("*");                   }                } +           else if (Pid == PATPID && synced && Processed) +              return Processed; // allow the caller to see any PAT packets             }          Data += TS_SIZE;          Length -= TS_SIZE; @@ -4,7 +4,7 @@   * See the main source file 'vdr.c' for copyright information and   * how to reach the author.   * - * $Id: remux.h 2.19 2009/08/16 15:15:33 kls Exp $ + * $Id: remux.h 2.20 2009/11/21 15:55:34 kls Exp $   */  #ifndef __REMUX_H @@ -49,6 +49,7 @@ public:  #define TS_ADAPT_TP_PRIVATE   0x02  #define TS_ADAPT_EXTENSION    0x01 +#define PATPID 0x0000 // PAT PID (constant 0)  #define MAXPID 0x2000 // for arrays that use a PID as the index  inline bool TsHasPayload(const uchar *p) @@ -238,8 +239,11 @@ public:         ///< Returns the PMT pid as defined by the current PAT.         ///< If no PAT has been received yet, -1 will be returned.    int Vpid(void) { return vpid; } -       ///< Returns the video pid as defined by the current PMT. +       ///< Returns the video pid as defined by the current PMT, or 0 if no video +       ///< pid has been detected, yet.    int Vtype(void) { return vtype; } +       ///< Returns the video stream type as defined by the current PMT, or 0 if no video +       ///< stream type has been detected, yet.    };  // TS to PES converter: @@ -299,6 +303,8 @@ void PesDump(const char *Name, const u_char *Data, int Length);  // Frame detector: +#define MIN_TS_PACKETS_FOR_FRAME_DETECTOR 2 +  class cFrameDetector {  private:    enum { MaxPtsValues = 150 }; @@ -320,7 +326,15 @@ private:    bool scanning;    uint32_t scanner;  public: -  cFrameDetector(int Pid, int Type); +  cFrameDetector(int Pid = 0, int Type = 0); +      ///< Sets up a frame detector for the given Pid and stream Type. +      ///< If no Pid and Type is given, they need to be set by a separate +      ///< call to SetPid(). +  void SetPid(int Pid, int Type); +      ///< Sets the Pid and stream Type to detect frames for. +  void Reset(void); +      ///< Resets any counters and flags used while syncing and prepares +      ///< the frame detector for actual work.    int Analyze(const uchar *Data, int Length);        ///< Analyzes the TS packets pointed to by Data. Length is the number of        ///< bytes Data points to, and must be a multiple of 188. diff --git a/ringbuffer.c b/ringbuffer.c index fd8123ec..1bdeaccc 100644 --- a/ringbuffer.c +++ b/ringbuffer.c @@ -7,7 +7,7 @@   * Parts of this file were inspired by the 'ringbuffy.c' from the   * LinuxDVB driver (see linuxtv.org).   * - * $Id: ringbuffer.c 2.2 2009/05/17 10:05:17 kls Exp $ + * $Id: ringbuffer.c 2.3 2009/11/22 11:14:36 kls Exp $   */  #include "ringbuffer.h" @@ -200,7 +200,7 @@ int cRingBufferLinear::Available(void)  void cRingBufferLinear::Clear(void)  { -  tail = head; +  tail = head = margin;  #ifdef DEBUGRINGBUFFERS    lastHead = head;    lastTail = tail; @@ -217,7 +217,8 @@ int cRingBufferLinear::Read(int FileHandle, int Max)    int free = (diff > 0) ? diff - 1 : Size() - head;    if (Tail <= margin)       free--; -  int Count = 0; +  int Count = -1; +  errno = EAGAIN;    if (free > 0) {       if (0 < Max && Max < free)          free = Max; @@ -247,6 +248,44 @@ int cRingBufferLinear::Read(int FileHandle, int Max)    return Count;  } +int cRingBufferLinear::Read(cUnbufferedFile *File, int Max) +{ +  int Tail = tail; +  int diff = Tail - head; +  int free = (diff > 0) ? diff - 1 : Size() - head; +  if (Tail <= margin) +     free--; +  int Count = -1; +  errno = EAGAIN; +  if (free > 0) { +     if (0 < Max && Max < free) +        free = Max; +     Count = File->Read(buffer + head, free); +     if (Count > 0) { +        int Head = head + Count; +        if (Head >= Size()) +           Head = margin; +        head = Head; +        if (statistics) { +           int fill = head - Tail; +           if (fill < 0) +              fill = Size() + fill; +           else if (fill >= Size()) +              fill = Size() - 1; +           UpdatePercentage(fill); +           } +        } +     } +#ifdef DEBUGRINGBUFFERS +  lastHead = head; +  lastPut = Count; +#endif +  EnableGet(); +  if (free == 0) +     WaitForPut(); +  return Count; +} +  int cRingBufferLinear::Put(const uchar *Data, int Count)  {    if (Count > 0) { diff --git a/ringbuffer.h b/ringbuffer.h index fa9ccedf..9fe33771 100644 --- a/ringbuffer.h +++ b/ringbuffer.h @@ -4,7 +4,7 @@   * See the main source file 'vdr.c' for copyright information and   * how to reach the author.   * - * $Id: ringbuffer.h 2.1 2009/03/01 11:20:34 kls Exp $ + * $Id: ringbuffer.h 2.2 2009/11/21 15:55:34 kls Exp $   */  #ifndef __RINGBUFFER_H @@ -84,6 +84,8 @@ public:      ///< Only one actual read() call is done.      ///< \return Returns the number of bytes actually read and stored, or      ///< an error value from the actual read() call. +  int Read(cUnbufferedFile *File, int Max = 0); +    ///< Like Read(int FileHandle, int Max), but reads fom a cUnbufferedFile).    int Put(const uchar *Data, int Count);      ///< Puts at most Count bytes of Data into the ring buffer.      ///< \return Returns the number of bytes actually stored. | 
