Mercurial > mplayer.hg
changeset 5584:f1519e4447a0
obsolete
author | arpi |
---|---|
date | Sat, 13 Apr 2002 01:42:23 +0000 |
parents | 70264cc9ade0 |
children | b7ced8012379 |
files | DOCS/tech/libmpcodecs.txt DOCS/tech/tech-hun.txt DOCS/tech/video-filters.txt |
diffstat | 3 files changed, 0 insertions(+), 382 deletions(-) [+] |
line wrap: on
line diff
--- a/DOCS/tech/libmpcodecs.txt Sat Apr 13 01:25:51 2002 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -# video decoder: - -int init(sh_video) -> loads codec dll, check if available and it accepts header if any - -int control(sh_video,cmd,param,...) -> various set/get/query functions - -int decode(sh_video,framedrop) -> decode frame, callbacks to config/get_surface - -int uninit(sh_video) - -# callbacks for video decoder: - -mpcodecs_config_vo(sh_video, w, h, preferred_outfmt){ - // it will be called by codec (either init() or decode()) when it gets - // enough info to know image dimensions, colorspaces and buffering type - - // this func should use control() to get/set parameters for a given outfmt - // (like supported buffering types, stride limitations, etc) or to - // query and select other colorspace. - -} - -// possible buffer setups: -- 1 static overwrite only (partial update type codecs: cvid, fli, vfw etc) -- 1+ independent temp writeonly (I-only mpegs, jpeg, mjpeg etc) -- 2+ static read/write (I+P mpegs) -- 2+ static read/write and 1+ temp writeonly (I+P+B mpegs) - -image_t* mpcodecs_get_surface(sh_video, flags){ -// flags: -// 0x1 - read (make it readable -> don't put to slow video ram) - -} -
--- a/DOCS/tech/tech-hun.txt Sat Apr 13 01:25:51 2002 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,296 +0,0 @@ -Nos, akkor leírom, hogyan is működik ez az egész. - -A fő modulok: - -1. streamer.c: ez az input layer, azaz ez olvassa a filet, VCD-t vagy stdin-t. - amit tudnia kell: megfelelő sectoronkénti 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 struktúra 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-enké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 file-okban vannak. - A hozzá tartozó struktúra a demuxer_t. Összesen egy demuxer van. - -2.a. demux_packet_t, azaz dp. - ez egy darab chunk-ot (avi) vagy packet-et (asf, mpg) tartalmaz. - memóriában ezek láncolt listában vannak, mivel különböző méretűek. - -2.b. demuxer stream, azaz ds. - struct: demux_stream_t - minden egyes csatornához (a/v) tartozik egy ilyen. - ez tartalmazza a stream-hez tartozó packeteket (lásd. 2.a.) - egyelőre demuxer-enként 3 ilyen lehet: - - hang (d_audio) - - kép (d_video) - - DVD felirat (d_dvdsub) - -2.c. stream header. 2 féle van (egyelőre): sh_audio_t és sh_video_t - ez tartalmaz minden, a dekódoláshoz szükséges paramétert, így az input - és output buffereket, kiválasztott codecet, fps/framerate stb adatokat. - Annyi van belőle, ahány stream van a file-ban tárolva. Lesz minimum egy - a videohoz, ha van hang akkor ahhoz is, de ha több audio/video stream - is van, akkor mindegyikhez lesz egy ilyen struct. - Ezeket avi/asf esetén a header alapján tölti fel a header beolvasó, - mpeg esetén pedig a demux_mpg.c fogja létrehozni, ha egy új streamet - talál. Új stream esetén ====> Found audio/video stream: <id> jelenik meg. - - A kiválasztott stream header és a hozzá tartozó demuxer stream kölcsönösen - hivatkoznak egymásra (ds->sh és sh->ds) az egyszerűbb használat végett. - (így a funkciótól függően elég vagy csak a ds vagy csak az sh átadása) - - Példa: van egy .asf file-unk, abban 6 db stream, ebből 1 audio és 5 video. - A header beolvasásakor létre fog jönni 6 db sh struct, 1 audio és 5 video. - Amikor elkezdi olvasni a packeteket, az első talált audio és video - packethez tartozó streamet kivalasztja, es ezekre allitja be a d_audio - és d_video sh pointereit. - Így a későbbiekben már csak ezeket a streameket olvassa, a többit nem. - Persze, ha a user másik streameket szeretne kiválasztani, akkor - force-olhatja az -aid és -vid kapcsolókkal. - Jó pelda erre a DVD, ahol nem mindig az angol szinkron hang az első - megtalált stream, és így random minden vob más nyelven szólalhat meg :) - Ilyenkor kell pl. az -aid 128 kapcsolót használni. - - hogy is műxik ez a beolvasósdi? - - meghívódik a demuxer.c/demux_read_data(), megkapja melyik ds-ből - (audio vagy video), mennyi byte-ot és hova (memóriacím) szeretnénk - beolvasni. Ezt hívogatják gyakorlatilag a codec-ek. - - ez megnézi, hogy az adott ds bufferében van-e valami, ha igen akkor - onnan olvas, amennyit kell. Ha nincs/nincs elég, akkor meghívja - a ds_fill_buffer()-t ami: - - megnézi, hogy az adott ds-ben vannak-e bufferelve csomagok (dp-k) - ha igen, akkor a legrégebbit átrakja a bufferbe és olvas tovább. Ha - üres a láncolt lista, akkor meghívja a demux_fill_buffer()-t: - - ez az input formátumnak megfelelő parser-t hívja meg, ami továbbol- - vassa a file-t, és a talált csomagokat berakja a megfelelő bufferbe. - Na, ha mondjuk audio csomagot szeretnénk, de csak egy rakat - video csomag van, akkor jön előbb-utóbb a DEMUXER: Too many - (%d in %d bytes) audio packets in the buffer... hibaüzenet. - -Eddig kb. tiszta ügy, ezt akarom majd átrakni külön lib-be. - -na nézzuk tovább: - -3. mplayer.c - igen, ő a főnök :) - - Fő feladata a különböző modulok összekapcsolása, illetve az A-V - szinkron biztosítása. - - Az adott stream aktuális pozíciója a megfelelo stream header - (sh_audio / sh_video) timer field-ben van. - (Régen ez volt az a_frame és egy v_frame nevű float változó) - - A lejátszó ciklus felépítése: - while(not EOF) { - fill audio buffer (read & decode audio) + increase a_frame - read & decode a single video frame + increase v_frame - sleep (wait until a_frame>=v_frame) - display the frame - apply A-V PTS correction to a_frame - check for keys -> pause,seek,... - } - - amikor lejátszik (hang/kép) akkor a lejátszott valami időtartamával - növeli a megfelelő változót: - - audionál ez a lejátszott byte-ok / sh_audio->o_bps - megj.: i_bps = tömörített byte-ok széma egy másodpercnyi hanghoz - o_bps = tömörítetlen byte-ok száma egy másodpercnyi hanghoz - (ez utóbbi == bps*samplerate*channels) - - videonál ez általában az sh_video->frametime. - Ez általában == 1.0/fps, persze meg kell jegyeznem, hogy videonál nem - igazán számít az fps, asf-nél pl. nincs is olyan, ahelyett duration - van és frame-enként változhat. - mpeg2-nél pedig repeat_count van, ami 1-2.5 időtartamban elnyújtja - a frame-et... avi-nál van talán egyedül fix fps, meg mpeg1-nél. - - Na most ez addig nagyon szépen működik, amíg a hang és kép tökéletes - szinkronban van, mivel így végülis a hang szól, az adja az időzítést, - és amikor eltelt egy frame-nyi idő, akkor kirakja a következő frame-et. - De mi van, ha valamiért az input file-ban csúszik a kettő? - Akkor jön be a PTS correction. Az input demuxer-ek olvassák a - csomagokkal együtt a hozzájuk tartozó PTS-t (presentation timestamp) - is, ami alapján észrevehető, ha el van csúszva a kettő. Ilyenkor egy - megadott maximális határon (lásd -mc opció) belül képes az mplayer - korrigalni az a_frame értékét. A korrekciók összege van a c_total-ban. - - Persze ez még nem minden szinkron ügyben, van még némi gáz. Pl. az, - hogy a hangkártya elég rendesen késleltet, ezt az mplayernek korrigálnia - kell! Az összes audio késleltetés másodpercben ezek összege: - - az utolsó timestamp (PTS) óta beolvasott byte-ok: - t1 = d_audio->pts_bytes/sh_audio->i_bps - - Win32/ACM esetén az audio input bufferben tárolt byte-ok: - t2 = a_in_buffer_len/sh_audio->i_bps - - az audio out bufferben tárolt tömörítetlen byte-ok: - t3 = a_buffer_len/sh_audio->o_bps - - a hangkártya bufferében (vagy DMA bufferben) tárolt, még nem - lejátszott byte-ok: - t4 = get_audio_delay()/sh_audio->o_bps - - Ezekből kiszámolható egészen pontosan, hogy az épp hallható hanghoz - milyen PTS tartozik, majd ezt összevetve a video-hoz tartozo PTS-el - meg is kapjuk az A-V eltérését! - - Avi-nál sem egyszerű az élet. Ott a 'hivatalos' időzítési mód a - BPS-alapú, azaz a headerben le van tárolva, hány tömörített audio - byte vagy chunk tartozik egy másodpercnyi (fps darab) képhez. - Az AVI stream headerben van 2 fontos mezo, a dwSampleSize, es - a dwRate/dwScale aránypár: - - Ha a dwSampleSize 0, akkor VBR stream, tehat nem konstans a - bitrate. Ilyenkor 1 chunk tarol 1 sample-t, es a masodpercenkenti - chunkok szamat adja a dwRate/dwScale. - - Ha a dwSampleSize>0, akkor constant bitrate van, es az ido igy - szamolhato: time = (bytepos/dwSampleSize) / (dwRate/dwScale) - (tehat a sample sorszamat elosztjuk a samplerate-el) - Ilyenkor stream-kent kezelheto az audio, ami tetszolegesen - chunk-okra van darabolva, de lehet akar 1 db chunk is az egesz. - - A másik lehetőség csak az interleaved fileoknál használható: a - chunk-ok sorrendjéből számolható egy timestamp (PTS) érték. - A video chunkok PTS-e egyszerű: chunk száma * fps - Az audio pedig az előtte levő video chunk-éval azonos. - Ilyenkor viszont szamolni kell az ugynev. "audio preload"-al is, - azaz van egy fix kesleltetes az audio es video stream-ek kozott. - Ez altalaban 0.5-1.0 sec, de van amikor egeszen mas. - A pontos erteket regen mertuk, most a demux_avi.c kezeli le: - az elso video utani audio chunknal kiszamolja az A-V elterest, - es ezt veszi az audio preload mertekenek. - -3.a. audio playback: - pár szó az audio lejátszásról: - az egészben nem maga a lejátszás a nehéz, hanem: - 1. hogy tudjuk, mikor lehet írni a bufferbe, blocking nélkül - 2. hogy tudjuk, mennyit játszott már le abból, amit a bufferbe írtunk - Az 1. az audio dekódoláshoz kell, valamint hogy a buffert mindig teli - állapotban tudjuk tartani (így sose fog megakadni a hang). - A 2. pedig a korrekt időzítéshez szükséges, ugyanis némely hangkártya - akár 3-7 másodpercet is késleltet, ami azért nem elhanyagolható! - Ezek megvalósítására az OSS többféle lehetőséget is kínál: - - ioctl(SNDCTL_DSP_GETODELAY): megmondja, hány lejátszatlan byte - várakozik a hangkártya bufferében -> időzítéshez kiváló, - de nem minden driver támogatja :( - - ioctl(SNDCTL_DSP_GETOSPACE): megmondja, mennyit írhatunk a kártya - bufferébe blocking nélkül. Ha a driver nem tudja a GETODELAY-t, - akkor ezt hasznalhatjuk arra is, hogy megtudjuk a késleltetést. - - select(): meg kéne mondja, hogy írhatunk-e a kártya bufferébe - blocking nélkül. Azt, hogy mennyit írhatunk, nem mondja meg :( - valamint sok driverrel egyáltalán nem, vagy rosszul működik :(( - csak akkor használom, ha egyik fenti ioctl() sem működik. - -4. codecek. ezek különböző lib-ek szanaszét mindenfelől. - mint pl. libac3, libmpeg2, xa/*, alaw.c, opendivx/*, loader, mp3lib. - - Az mplayer.c nem kozvetlenul hivja oket, hanem a dec_audio.c es a - dec_video.c fileokon keresztul, igy az mplayer.c-nek nem kell semmit - sem tudnia a codecrol. - -5. libvo: ez végzi a kép kirakását. - - Az img_format.h-ban definiálva vannak konstansok a különböző pixel- - formátumokhoz, ezeket kötelező használni. - - 1-1 vo drivernek a következőket kell kötelezően implementálnia: - - query_format() - lekérdezi, hogy egy adott pixelformat támogatott-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 drivernek kötelező támogatnia az YV12 formátumot, és - egyiket (vagy mindkettőt) a BGR15 és BGR24 közül, ha kell, konvertálással. - Ha ezeket nem támogatja, akkor nem fog minden codec-kel működni! - Ennek az az oka, hogy az mpeg codecek csak YV12-t tudnak előállítani, - a régebbi Win32 DLL codecek pedig csak 15 és 24bpp-t tudnak. - Van egy gyors MMX-es 15->16bpp konvertáló, így az nem okoz különösebb - sebességcsökkenést! - - A BPP táblázat, ha a driver nem tud bpp-t váltani: - jelenlegi bpp: ezeket kell elfogadni: - 15 15 - 16 15,16 - 24 24 - 24,32 24,32 - - Ha tud bpp-t váltani (pl. DGA 2, fbdev, svgalib) akkor, ha lehet, be kell - váltani a kért bpp-re. Ha azt a hardver nem támogatja, akkor a legközelebbi - módra (15 esetén 16-ra, 24 esetén 32-re) kell váltani és konvertálni! - - init() - ez hívódik meg a legelső frame kirakása előtt - bufferek foglalása - stb a célja. - van egy flags paraméter is (régen fullscreen volt a neve): - 0x01 - fullscreen (-fs) - 0x02 - vidmode switch (-vm) - 0x04 - scaling enabled (-zoom) - 0x08 - flip image (upside-down) - - draw_slice(): ez planar YV12 képet rak ki (3 db plane, egy teljes - méretű, ami a fényerőt (Y) tartalmazza, és 2 negyedakkora, ami a - szín (U,V) infót). ezt használják az mpeg codecek (libmpeg2, opendivx). - ez már tud olyat, hogy nem az egész kép kirakása, hanem csak kis - részletek update-elése: ilyenkor a sarkának és a darabka méretének - megadásával lehet használni. - - draw_frame(): ez a régebbi interface, ez csak komplett frame-et rak ki, - és csak packed formátumot (YUY2 stb, RGB/BGR) tud. - ezt használják a win32 codecek (divx, indeo stb). - - draw_alpha(): ez rakja ki a subtitle-t és az OSD-t. - használata kicsit cseles, mivel ez nem a libvo API része, hanem egy - callback jellegű cucc. a flip_page() kell meghívja a vo_draw_text()-et - úgy, hogy paraméterként átadja a képernyő méreteit és a pixel- - formátumnak megfelelő draw_alpha() implementációt (function pointer). - Ezután a vo_draw_text() végigmegy a kirajzolandó karaktereken, és - egyenként meghívja minden karakterre a draw_alpha()-t. - Segítség képpen az osd.c-ben meg van írva a draw_alpha mindenféle - pixelformátumhoz, ha lehet ezt használd! - - flip_page(): ez meghívódik minden frame után, ennek kell ténylegesen meg- - jeleníteni a buffert. double buffering esetén ez lesz a 'swapbuffers'. - -6. libao2: ez vezérli a hang lejátszást - - A libvo-hoz (lásd 5.) hasonlóan itt is különböző driverek vannak, amik - egy közös API-t (interface) valósítanak meg: - -static int control(int cmd,int arg); - Ez egy általános célú függvény, a driverfüggő és egyéb speciális paraméterek - olvasására/beállítására. Egyelőre nem nagyon használt. - -static int init(int rate,int channels,int format,int flags); - Driver initje, ilyenkor kell megnyitni a device-t, beállítani samplerate, - channels, sample format paramétereket. - Sample format: általában AFMT_S16_LE vagy AFMT_U8, további definíciókért - lásd. dec_audio.c ill. linux/soundcard.h file-okat! - -static void uninit(); - Találd ki! - Na jó, segítek: lezárja a device-t, kilépéskor (még nem) hívódik meg. - -static void reset(); - Reseteli a device-t. Egész pontosan a bufferek törlésére szolgál, - tehát hogy a reset() után már ne szóljon tovább az, amit előtte kapott. - (pause ill. seek esetén hívódik meg) - -static int get_space(); - Vissza kell adja, hogy hány byte írható az audio bufferbe anélkül, hogy - blockolna (várakoztatná a hívó processt). Amennyiben a buffer (majdnem) - tele van, 0-t kell visszaadni! - Ha sosem ad vissza 0-t, akkor nem fog működni az MPlayer! - -static int play(void* data,int len,int flags); - Lejátszik egy adag hangot, amit a data című memóriaterületen kap és len - a mérete. a flags még nem használt. Az adatokat át kell másolnia, mert a - hívás után felülíródhatnak! Nem kell feltétlen minden byte-ot felhasználni, - hanem azt kell visszaadnia, mennyit használt fel (másolt a bufferbe). - -static int get_delay(); - Visszaadja meddig fog tartani az éppen az audio bufferben levő adat - lejátszása. Lehetőleg minél pontosabban, mert ettől függ az egész időzítés! - Legrosszabb esetben adja vissza a maximális időzítést. - -!!! Mivel a kép a hanghoz (hangkártyához) van szinkronizálva, így nagyon fontos, -!!! hogy a get_space ill. get_delay függvények korrektül legyenek megírva! - -6.a Audio plugin-ek - Remélem tudsz angolul.
--- a/DOCS/tech/video-filters.txt Sat Apr 13 01:25:51 2002 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -First draft on video filter layer by A'rpi -================================= - -Main goals: -- it should be in libmpcodecs -- it should reduce number of memcpys and memoru allocation to minimum -- it should do postprocessing, colorspace convert, scale and crop/expand/flip - [is there any other type of filters? maybe we could generalize these] -- maybe: sub/osd - -Implementation: - -The video filter plugin should implement the get_image() call (called from -the video decoder) and call get_image() for the destination image. - -so, it would have: - -optional: - int get_image(mp_image_t* mpi) // called through control() - - if the filter doesn't implement this call, the core (vd.c) will alloc - buffer using memalign() as for disabled direct rendering. - -mandatory: - mp_vfilter_data* init() - - void uninit(mp_vfilter_data* vfd) - - int control(mp_vfilter_data* vfd, ...) - - mp_image_t* process(mp_vfilter_data* vfd, mp_image_t* mpi,(*get_image)()) - - this function will receive an mpi (maybe previously returned by get_image()) - and should return the filtered mpi. it should use mpcodecs_get_image() to - allocate a new mpi. - the returned mpi may be EXPORT type, so just doing some pointer/stride - tricks (usually enough for crop/expand/flip) without duplicating the - image buffer or doing the modifications in the incoming buffer (if its - type allows it - so no flags PRESERVE/READABLE set) - -mp_vfilter_data would be a transparent (to caller) pointer, used by the -filter instance to store its internal data, tables, parameters etc. -it would allow a fliter to be used more than one times in the queue. -for example: resize in 2 step, postproc+resize+postproc, expand+scale+crop etc - -the tricky part of these filters is finding and implementing Direct -Filtering(C) using get_image(). - -anyway, as first step you can skip get_image() implementation, and just -leave it to vd.c core. in most cases it will be enough, direct filtering -only helps with simple filters (crop/expand/flip) in most cases. -