aboutsummaryrefslogtreecommitdiffhomepage
path: root/DOCS/tech/tech-hun.txt
blob: e44911479f8f6ffd8d891e72b9646cfbe0a37fc6 (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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
[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ő sectoronkenti 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 csatorná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. 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.

2.b. demuxer stream, azaz ds. struct: demux_stream_t
   minden egyes csatornahoz (a/v) tartozik egy ilyen.
	 ez tartalmazza a stream-hez tartozo packeteket (lasd. 2.a.)
	 egyelore demuxer-enkent 2 ilyen lehet, egy a hanghoz es egy a kephez.

2.c. stream header. 2 fele van (egyelore): sh_audio_t es sh_video_t
   ez tartalmaz minden, a dekodolashoz szukseges parametert, igy az input
   es output buffereket, kivalasztott codecet, fps/framerate stb adatokat.
   Annyi van belole, ahany stream van a fileban tarolva. Lesz minimum egy
   a videohoz, ha van hang akkor ahhoz is, de ha tobb audio/video stream
   is van, akkor mindegyikhez lesz egy ilyen struct.
   Ezeket avi/asf eseten a header alapjan tolti fel a header beolvaso,
   mpeg eseten pedig a demux_mpg.c fogja letrehozni ha egy uj streamet
   talal. Uj stream eseten ====> Found audio/video stream: <id>  jelenik meg.
   
   A kivalasztott stream header es a hozza tartozo demuxer stream kolcsonosen
   hivatkoznak egymasra (ds->sh es sh->ds) az egyszerubb hasznalat miatt.
   (igy a funkciotol fuggoen eleg vagy csak a ds vagy csak az sh atadasa)
   
   Pelda: van egy .asf fileunk, abban 6 db stream, ebbol 1 audio es 5 video.
   A header beolvasasakor letre fog jonni 6 db sh struct, 1 audio es 5 video.
   Amikor elkezdi olvasni a packeteket, az elso talalt audio es video streamet
   kivalasztja, es ezekre allitja be a d_audio es d_video sh pointereit.
   Igy kesobbiekben mar csak ezeket a streameket olvassa, a tobbit nem.
   Persze ha az user masik streameket szeretne kivalasztani, akkor
   force-olhatja a -aid es -vid kapcsolokkal.
   Jo pelda erre a DVD, ahol nem mindig az angol szinkron hang az elso
   megtalalt stream, es igy random minden vob mas nyelven szolalhat meg :)
   Ilyenkor kell pl. az -aid 128 kaocsolot hasznalni.
   
  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).
	 parameterkent a megfelelo stream headert (sh_audio/sh_video) kell
	 atadni, ez elvileg tartalmaz minden infot ami szukseges a
	 dekodolashoz (tobbek kozott a demuxert is: sh->ds).
   A codecek szeparalasa folyamatban van, az audio mar el van kulonitve
   (lasd. dec_audio.c), a videon meg dolgozunk. Cel, hogy ne az mplayer.c
   kelljen tudja milyen codecek vannak es hogy kell oket hasznalni, hanem
   egy kozos init/decode audio/video functiont kelljen csak meghivnia.

5. libvo: ez vegzi a kep kirakasat.

  Az img_format.h-ban definialva vannak konstansok a kulonbozo pixel-
  formatumokhoz, ezeket kotelezo hasznalni.
  
  1-1 vo driver a kovetkezoket kell kotelezoen implementalja:

  query_format()  - lekerdezi hogy egy adott pixelformat tamogatott-e.
                    return value:  flags:
		       0x1 - supported (by hardware or with conversion)
		       0x2 - supported (by hardware, without conversion)
		       0x4 - sub/osd supported (has draw_alpha)
  FONTOS: minden vo driver kotelezo tamogassa az YV12 formatumot, es
  egyiket (vagy mindkettot) a BGR15 es BGR24 kozul, ha kell, konvertalassal.
  Ha ezeket nem tamogatja, akkor nem fog minden codec-kel mukodni!
  Ennek az az oka, hogy az mpeg codecek csak YV12-t tudnak eloallitani,
  a regebbi Win32 DLL codecek pedig csak 15 es 24bpp-t tudnak.
  Van egy gyors MMX-es 15->16bpp konvertalo, igy az nem okoz kulonosebb
  sebessegcsokkenest!
  
  A BPP tablazat, ha a driver nem tud bpp-t valtani:
      jelenlegi bpp:    ezeket kell elfogadni:
           15                    15
	   16                    15,16
	   24                    24
	   24,32                 24,32

  Ha tud bpp-t valtani (pl. DGA 2, fbdev, svgalib) akkor ha lehet, be kell
  valtani a kert bpp-re. Ha azt a hardver nem tamogatja, akkor a legkozelebbi
  modra (15 eseten 16-ra, 24 eseten 32-re) kell valtani es konvertalni!

  init() - ez hivodik meg a legelso frame kirakasa elott - bufferek foglalasa
           stb a celja.

  draw_slice(): ez planar YV12 kepet rak ki (3 db plane, egy teljes
	 meretu ami a fenyerot (Y) tartalmazza, es 2 negyedakkora, ami a
	 szin (U,V) 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.

  draw_frame(): ez a regebbi interface, ez csak komplett framet rak ki,
   es csak packed formatumot (YUY2 stb, RGB/BGR) tud.
	 ezt hasznaljak a win32 codecek (divx,indeo stb).
	 
  draw_alpha(): ez rakja ki a subtitle-t es az OSD-t.
   hasznalata kicsit cseles, mivel ez nem a libvo API resze, hanem egy
   callback jellegu cucc. a flip_page() kell meghivja a vo_draw_text()-et
   ugy, hogy parameterkent atadja a kepernyo mereteit es a pixelformatumnak
   megfelelo draw_alpha() implementaciot (function pointer).
   Ezutan a vo_draw_text() vegigmegy a kirajzolando karaktereken, es egyenkent
   meghivja minden karakterre a draw_alpha()-t.
   Segitseg keppen az osd.c-ben meg van irva a draw_alpha mindenfele
   pixelformatumhoz, ha lehet ezt hasznald!
   
  flip_page(): ez meghivodik minden frame utan, ez kell tenylegesen
   megjelenitse a buffert. double buffering eseten ez lesz a 'swapbuffers'.