summaryrefslogtreecommitdiffstats
path: root/DOCS/tech/tech-hun.txt
blob: 5d2ecfa283756d954caf8cfe63c9262691c2b27e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
[yes, this is hungarian. maybe someone will translate this to russian or
something else...]

Nos, akkor leirom, hogyan is működik ez az egész.

Az ékezetekkel majd lesz valami, nem nagyon vagyok hozzászokva az
ékezetes gépeléshez...

A program felépítése alapjaiban logikus, de eleg gányul van megirva :)

A fő modulok:

1. streamer.c: ez az input, azaz ez olvassa a filet vagy VCD-t.
   amit tudnia kell: megfelelő bufferelés, seek, skip funkciók,
	 byte-onkénti ill. tetszőleges méretű blockonkénti olvasás.
	 Egy stream (input device/file) leírására a stream_t struktura szolgál.
	 
2. demuxer.c: ez végzi az input szétszedését audio és video csatornákra,
   és a kiválasztott scatornák bufferelt package-nkénti olvasását.
	 A demuxer.c inkább csak egy framework, ami közös minden input
	 formátumra, és az egyes formátumokhoz (mpeg-es,mpeg-ps, avi, avi-ni, asf)
	 külön parser van, ezek a demux_*.c fileokban vannak.
	 A hozza tartozo struktura a demuxer_t. osszesen egy demuxer van.
	 
2.a. demuxer stream, azaz ds. struct: demux_stream_t
   minden egyes csatornahoz (a/v) tartozik egy ilyen.
	 egyelore demuxer-enkent 2 ilyen lehet, egy a hanghoz es egy a kephez.
	 
2.b. demux_packet_t, azaz dp.
   ez egy darab chunk-ot (avi) vagy packet-et (asf,mpg) tartalmaz.
	 memoriaban ezek lancolt listaban vannak, mivel kulonbozo meretuek.

  hogy is muxik ez a beolvasosdi?
	 - meghivodik a demuxer.c/demux_read_data(), megkapja melyik ds-bol
	   (audio vagy video), mennyi byteot es hova (memoriacim) szeretnenk 
		 beolvasni. ezt hivogatjak gyakorlatilag a codec-ek.
	 - ez megenzi,hogy az adott ds bufferében van-e valami, ha igen akkor 
	   onnan olvas amennyit kell. ha nincs/nincs eleg, akkor meghivja
		 a ds_fill_buffer()-t ami:
	 - megnezi hogy az adott ds-ben vannak-e bufferelve csomagok (dp-k)
	   ha igen, akkor a legregebbit atrakja a bufferbe es olvas tovabb.
		 ha ures a lancolt lista, akkor meghivja a demux_fill_buffer()-t:
	 - ez az input formatumnak megfelelo parset meghivja ami olvassa
	   tovabb a filet, es a talalt csomagokat rakja be a megfelelo bufferbe.
		 na ha mondjuk audio csomagot szeretennk, de csak egy rakat video csomag
		 van, akkor jon elobb-utobb a DEMUXER: Too many (%d in %d bytes) audio 
		 packets in the buffer... hibauzenet.

Eddig kb tiszta ugy, ezt akarom majd atrakni kulon lib-be.

na nezzuk tovabb:

3. mplayer.c - igen, o a fonok :)
   az idozites eleg erdekesen van megoldva, foleg azert mert minden
	 fileformatumnal maskepp kell/celszeru, es neha tobbfele keppen is lehet.
	 van egy a_frame es egy v_frame nevu float valtozo, ez tarolja az epp
	 lathato/hallhato a/v poziciojat masodpercben.
	 akkor jelenit meg ujabb video frame-t, ha v_frame<a_frame, es akkor
	 dekodol tovabb hangot ha a_frame<v_frame.
	 amikor lejatszik (hang/kep) akkor a lejatszott valami idotartamaval
	 noveli a megfelelo valtozot. videonal ez altalaban 1.0/fps, persze
	 meg kell jegyeznem hogy videonal nem igazna szamit az fps, asf-nel
	 pl. nincs is olyan, ahelyett duration van es framenkent valtozhat.
	 mpeg2-nel pedig repeat_count van ami 1-2.5 idotartamban elnyujtja
	 a framet... avi-nal van talan egyedul fix fps, meg mpeg1-nel.

	 Na most ez addig nagyon szepen mukodik, amig a hang es kep tokeletes
	 szinkronban van, mivel igy vegulis a hang szol, az adja az idozitest,
	 es amikor eltelt egy framenyi ido akkor kirakja a kovetkezo framet.
	 de mi van ha valamiert az input fileban csuszik a ketto?
	 Akkor jon be a PTS correction. az input demuxer-ek olvassak a csomagokkal
	 egyutt a hozzajuk tartozo PTS-t (presentation timestamp) is, ami alapjan
	 eszreveheto ha el van csuszva a ketto. ilyenkor egy megadott maximalis
	 hataron (lasd -mc opcio) belul kepes az mplayer korrigalni az a_frame 
	 erteket. a korrekciok osszege van a c_total-ban.
	 
	 persze ez meg nem minden szinkron ugyben, van meg nemi gaz.
	 pl. az hogy a hangkartya eleg rendesen kesleltet, ezt az mplayernek
	 korrigalnia kell: ezert kell neki az audio buffer merete. amit a
	 select()-e tud lemerni amit viszont nem tud minden kartya...
	 ilyenkor kell a -abs opcioval megadni.
	 
	 aztan van olyan gond is, hogy pl. mpegnel nem framenkent van PTS
	 hanem szektoronkent, ami tartalmazhat 10 framet is de 0.1-et is.
	 hogy ez ne csessze el az idozitest, atlagoljuk 5 framenkent a 
	 PTS-t es ezt az atlag erteket vesszuk figyelembe korrekcional.
	 
	 avi-nal sem egyszeru az elet. ott a 'hivatalos' idozitesi mod a
	 BPS-alapu, azaz a headerben le van tarolva hany tomoritett audio
	 byte tartozik egy masodpercnyi (fps darab) kephez.
	 ez persze nem mindig mukodik... miert is mukodne :)
	 ezert en megcsinaltam hogy az mpeg-nel hasznalatos sectoronkenti
	 PTS erteket emulalom avi-ra is, azaz az AVI parser minden beolvasott
	 chunk-nal szamol egy kamu PTS-t a framek tipusa alapjan. es ez
	 alapjan idozitek. es van amikor ez mukodik jobban.
	 persze itt meg bejatszik az is, hogy AVI-nal altalaban elore letarolnak
	 egy nagyobb adag hangot, es csak utana kezdodik a kep. ezt persze
	 bele kell szamolni a kesleltetesbe, ez az Initial PTS delay.
	 ilyen persze 2 is van, az egyik a headerben le is van irva, es
	 nem nagyon hasznlajak :) a masik sehol nincs leirva de hasznaljak, ezt
	 csak merni lehet...
	 
4. codecek. ezek kulonbozo lib-ek szanaszet mindenfelol.
   mint pl. libac3, libmpeg2, xa/*, alaw.c, opendivx/*, loader, mp3lib.
	 az mplayer.c hivogatja oket amikor egy egy darab hangot vagy framet
	 kell lejatszani (lasd 3. pont elejen)
	 ezek pedig hivjak a megfelelo demuxert hogy megkapjak a tomoritett
	 adatokat (lasd 2. pont).
	 
4.a codec controller: na ez a legnagypbb gány az egeszben :)
	 a libmpeg2 ugyanis annyira instabil hogy az mar hatareset.
	 persze ezt nem ugy kell erteni hogy szar :) hanem ugy, hogy csak
	 teljesen szabvanyos, hibatlan mpeg streamet eszik meg. ha hibat
	 talal, egyszeruen segfault ;)  es nem rohogni, ez nagyon jo igy,
	 teljesitmeny szempontbol 50-100%-al lasabb lenne ha teleraknak
	 ellenorzesekkel. ezert csinaltam azt a megoldast, hogy kulon
	 processzben futtatom, es ha elszall, hat kit izgat, majd inditok
	 egy masikat. ehhez azert kell par dolog:
	 - codec controller process: egy kulon processz, ami sleep-el, de
	   ha a gyereke (a libmpeg2 processz) meghal, akkor indit gyorsan
		 egy masikat. igy az mplayer-nek nem kell ezzel fogallkoznia, o
		 csak pumpalja a gyerekbe a tomoritett adatot az meg rakja kifele.
	 - shmem: a tomoritett adatok, es a kitomoritett framek is shared
	   memoryban vannak, tehat mind a 3 processz (mplayer, codeccontrol,
		 libmpeg2 codec) is latja. igy tudnak gyorsan adatot cserelni.
	 - a koztuk levo kommunikaciora meg FIFO van.
	 - valamint ha dekodolas kozben meghal a gyerek, az altala sikeresen
		 dekodolt adatok nem vesznek el, hanem a shmem-en keresztul oroklodik
		 az uj gyereknek! ezert max egy pici hiba latszik a kepen, nem tunik
		 el az egesz meg zoldul be, mint a regi verzioban.
	 hatranya ennek az egesznek, hogy a libvo-libmpeg2 szoros kapcsolodasa
	 miatt a libvo is abban a processzben kell fusson, amiben a libmpeg2,
	 tehat abban ami allandoan megdoglik-ujraszuletik, es nem abban amiben
	 a vezerlo processz, az mplayer fut. ez eleg sok gondot okozik, foleg
	 a libvo ablakban tortent esemenyek (billentyunyomas pl) kezelesekor.
	 erre mindenfele workaroundok vannak, FIFO-k minden mennyisegben, meg
	 trukk ami kihasznalja hogy az X-nek mind1 melyik processz kerdezi
	 le az Event-jeit.
	 
	 szeretnem a kozeljovoben ezt megszuntetni, es az mpeg2dec-devel
	 listan kidolgozott signal/longjmp (szinten gány :)) modszert hasznalni.

5. libvo: ez vegzi a kep kirakasat. jelenleg 2 kulonbozo kepkirako
   van benne:
5.a draw_slice(): ez planar YV12 kepet rak ki (3 db frame, egy teljes
	 meretu ami a fenyerot tartalmazza, es 2 negyedakkora, ami a
	 szin infot). ezt hasznaljak az mpeg codecek (libmpeg2,opendivx).
	 ez mar tud olyat hogy nem az egesz kep kirakasa, hanem csak kis
	 reszletek updatelese: ilyenkor a sarkanak es a darabka meretenek
	 megadasaval lehet csinalni.
5.b draw_frame(): ez a regebbi interface, ez csak komplett framet rak ki,
   es csak packed formatumot (YUY2, RGB/BGR) tud.
	 ezt hasznaljak a win32 codecek (divx,indeo stb).