mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Fixed generating the index for recordings from channels that put a whole GOP into one payload unit; regenerating index file
This commit is contained in:
parent
2db303d6f5
commit
8ffbea3788
10
HISTORY
10
HISTORY
@ -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.
|
||||
|
@ -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 !"
|
||||
|
||||
|
@ -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: Vladimír Bárta <vladimir.barta@k2atmitec.cz>, Jiøí Dobrý <jdobry@centrum.cz>\n"
|
||||
"Language-Team: Czech\n"
|
||||
@ -925,6 +925,12 @@ msgstr "Kan
|
||||
msgid "Low disk space!"
|
||||
msgstr "Disk bude brzy zaplnìn!"
|
||||
|
||||
msgid "Regenerating index file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Index file regeneration complete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Can't shutdown - option '-s' not given!"
|
||||
msgstr "Vypnutí není mo¾né - chybí volba '-s'!"
|
||||
|
||||
|
@ -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!"
|
||||
|
||||
|
@ -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 unmöglich - Option '-s' fehlt!"
|
||||
|
||||
|
@ -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'!"
|
||||
|
||||
|
@ -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 "
|
||||
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 parámetro '-s'!"
|
||||
|
||||
|
@ -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 "Kõvaketas täis!"
|
||||
|
||||
msgid "Regenerating index file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Index file regeneration complete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Can't shutdown - option '-s' not given!"
|
||||
msgstr "Väljalülitamine ebaõnnestus - '-s' parameeter puudub!"
|
||||
|
||||
|
@ -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 k
|
||||
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!"
|
||||
|
||||
|
@ -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 "Cha
|
||||
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 "Arrêt impossible - option '-s' absente !"
|
||||
|
||||
|
@ -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 zaklju
|
||||
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 "Ga¹enje nemoguæe - nedostaje opcija '-s'!"
|
||||
|
||||
|
@ -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: István Füley <ifuley@tigercomp.ro>\n"
|
||||
"Language-Team: Hungarian\n"
|
||||
@ -927,6 +927,12 @@ msgstr "Az ad
|
||||
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 leállítás nem lehetséges - Opció '-s' hiányzik!"
|
||||
|
||||
|
@ -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!"
|
||||
|
||||
|
@ -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'!"
|
||||
|
||||
|
@ -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!"
|
||||
|
||||
|
@ -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 l
|
||||
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'!"
|
||||
|
||||
|
@ -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
|
||||
msgid "Low disk space!"
|
||||
msgstr "Mało miejsca na dysku!"
|
||||
|
||||
msgid "Regenerating index file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Index file regeneration complete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Can't shutdown - option '-s' not given!"
|
||||
msgstr "Nie można wyłączyć - nie podano opcji '-s'!"
|
||||
|
||||
|
@ -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 "Espaço em disco reduzido!"
|
||||
|
||||
msgid "Regenerating index file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Index file regeneration complete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Can't shutdown - option '-s' not given!"
|
||||
msgstr "Impossível desligar - falta a opção '-s'!"
|
||||
|
||||
|
@ -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 (
|
||||
msgid "Low disk space!"
|
||||
msgstr "Spaþiul pe disc e foarte scãzut!"
|
||||
|
||||
msgid "Regenerating index file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Index file regeneration complete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Can't shutdown - option '-s' not given!"
|
||||
msgstr "Nu pot închide - vezi opþiunea '-s'"
|
||||
|
||||
|
@ -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'!"
|
||||
|
||||
|
@ -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 "Kan
|
||||
msgid "Low disk space!"
|
||||
msgstr "Za chvíµku 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 mo¾né - chýba voµba '-s'!"
|
||||
|
||||
@ -1023,4 +1029,3 @@ msgstr "ktor
|
||||
#, c-format
|
||||
msgid "VDR will shut down in %s minutes"
|
||||
msgstr "VDR sa vypne za %s minút"
|
||||
|
||||
|
@ -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!"
|
||||
|
||||
|
@ -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
|
||||
msgid "Low disk space!"
|
||||
msgstr "Lågt diskutrymme!"
|
||||
|
||||
msgid "Regenerating index file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Index file regeneration complete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Can't shutdown - option '-s' not given!"
|
||||
msgstr "Kan inte avsluta, måste använda parameter '-s'"
|
||||
|
||||
|
@ -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 Yolgeçen <oktay_73@yahoo.de>\n"
|
||||
"Language-Team: Turkish\n"
|
||||
@ -924,6 +924,12 @@ msgstr "Kanal ge
|
||||
msgid "Low disk space!"
|
||||
msgstr "Kayýt kapasitesi az!"
|
||||
|
||||
msgid "Regenerating index file"
|
||||
msgstr ""
|
||||
|
||||
msgid "Index file regeneration complete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Can't shutdown - option '-s' not given!"
|
||||
msgstr "Kapatýlamýyor - '-s' seçeneði verilmemiþ!"
|
||||
|
||||
|
@ -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'!"
|
||||
|
||||
|
@ -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;
|
||||
|
150
recording.c
150
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
|
||||
|
@ -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 {
|
||||
|
310
remux.c
310
remux.c
@ -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;
|
||||
}
|
||||
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 // 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 = 0;
|
||||
scanning = true;
|
||||
}
|
||||
if (scanning) {
|
||||
int PayloadOffset = TsPayloadOffset(Data);
|
||||
if (TsHasPayload(Data) && !TsIsScrambled(Data)) {
|
||||
int Pid = TsPid(Data);
|
||||
if (Pid == pid) {
|
||||
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;
|
||||
}
|
||||
else {
|
||||
framesInPayloadUnit++;
|
||||
if (independentFrame)
|
||||
numIFrames++;
|
||||
dbgframes("%d ", (Data[i + 2] >> 3) & 0x07);
|
||||
}
|
||||
scanner = 0;
|
||||
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)
|
||||
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
|
||||
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 {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
scanner = EMPTY_SCANNER;
|
||||
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
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
break;
|
||||
case 0x04: // MPEG audio
|
||||
case 0x06: // AC3 audio
|
||||
if (synced && Processed)
|
||||
return Processed;
|
||||
newFrame = true;
|
||||
independentFrame = true;
|
||||
if (!synced) {
|
||||
framesInPayloadUnit = 1;
|
||||
if (TsPayloadStart(Data))
|
||||
numIFrames++;
|
||||
}
|
||||
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;
|
||||
|
20
remux.h
20
remux.h
@ -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.
|
||||
|
45
ringbuffer.c
45
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) {
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user