diff options
Diffstat (limited to 'DOCS/OUTDATED-tech/realcodecs')
-rw-r--r-- | DOCS/OUTDATED-tech/realcodecs/TODO | 22 | ||||
-rw-r--r-- | DOCS/OUTDATED-tech/realcodecs/audio-codecs.txt | 155 | ||||
-rw-r--r-- | DOCS/OUTDATED-tech/realcodecs/streaming.txt | 58 | ||||
-rw-r--r-- | DOCS/OUTDATED-tech/realcodecs/video-codecs.txt | 185 |
4 files changed, 420 insertions, 0 deletions
diff --git a/DOCS/OUTDATED-tech/realcodecs/TODO b/DOCS/OUTDATED-tech/realcodecs/TODO new file mode 100644 index 0000000000..5ba035bfdd --- /dev/null +++ b/DOCS/OUTDATED-tech/realcodecs/TODO @@ -0,0 +1,22 @@ +TODO: + +- more docs are coming as I find the time to write them down +- use RV20toYUV420Free() +- audio support - nearly DONE (look below) +- internet streaming support +- searching - we need to take care of the audio interleaving - + haven't taken steps to locate audio key frames (does such thing + exist?) +- some media files can't be played (mplayer crashes/fails) because + it asks for decoded audio data, but the buffer in the audio + demuxer packets are empty/missing. It seems that the necessary + audio packets haven't been decoded completely (incomplete interleaving) + the audio stream packets may get mixed with video stream packet - DONE ??? +- put variables for audio streaming inside real_priv_t +- audio support for other formats than COOK - use a switch + (like -forcereal) to activate it - no switch needed, win32 codecs + doens't work (it was a nonworking attempt) +- postprocessing support (see rp8 preferences->performance->cpu usage, + also statistics->streams->video->POST FILTER: ON + (i've found that custommessage calls differ wiht pp on/off, but adding + these calls to mplayer didn't make a pixel difference between outputs) diff --git a/DOCS/OUTDATED-tech/realcodecs/audio-codecs.txt b/DOCS/OUTDATED-tech/realcodecs/audio-codecs.txt new file mode 100644 index 0000000000..fd28ab2a16 --- /dev/null +++ b/DOCS/OUTDATED-tech/realcodecs/audio-codecs.txt @@ -0,0 +1,155 @@ +all audio codecs (cook,atrk,14_4,28_8,dnet,sipr) have the same interface, +but i have only analyzed the cook codec + + +audio properties (hex) + +00 short text/description of the format (bitrate, when to use) +01 bitrate (bits/s) //avg. bytes/sec output +02 ulong: ? + ulong: samples per second + ushort: bits/sample + ushort: number of channels +03 same as 02 //constant 2 +04 long description +05 constant 1 (always?) +06 ulong: block align (input frame size for RADecode) +07 string: minimum player version +08 n/a +09 n/a +0A n/a +0B n/a +0C n/a +0D ? +0E ? leaf size +0F ? +10 ? +11 ? +12 ? +13 min. output buffer size? max. number of samples? +14 ? + + + + +functions: + +ulong result=RAOpenCodec2(ra_main_t *raMain); + +ulong result=RAInitDecoder(ra_main_t *raMain, ra_init_struct *raInit); +struct ra_init_struct { + ulong sample_rate; + ushort bits_per_sample; // unused by RAInitDecoder + ushort number_of_channels; + ushort unknown1; // 0 + ushort unknown2; // also unused (100) + ulong leaf_size; // leaf size (used for interleaving, but + // exists in audio stream description header (ASDH)) + ulong block_align; // packet size + ulong bits_per_sample; // unused (always 16) + char *ext_data; // 16 bytes located at the end of the + // ASDH +}; + +There are some information missing that you usually need for playback, +like bits per sample (the fileds aren't read by RAInitDecoder()). These +are hard coded in the "flavors", i.e. the sub formats. A flavor is an entry +in the list of available format variations like bitrate, number of channels, +decoding algorithm, and so on.We can get those information with the +following command: + + + +void *GetRAFlavorProperty(ra_main_t *raMain, ulong flavor, ulong property, + short *property_length_in_bytes); +returns property data for a specific data + +This is not important, because it's just a read only function. +These flavor properties don't seem to exist in + + +ulong RADecode(ra_main_t *raMain, char *input_buffer, + ulong input_buffer_size, char *output_buffer, + ulong *decoded_bytes, ulong p6=-1); + +RAFreeDecoder(ra_main_t *); + +RACloseCodec(ra_main_t *); + + +ulong RASetFlavor(ra_main_t *ra_main, ulong flavor); + +Set the flavor of the stream. + +a flavor is an entry in the list of available format variations like +bitrate, number of channels, decoding algorithm, and so on + + +audio data storage: +------------------- + +With Real Audio V5 (or earlier?), the audio streams can be interleaved, +i.e. the stream is striped amongst several data packets. The packets +(which have a fixed size packet_len) are split up into a fixed number +of num_parts equally sized parts - I call them leaves in lack of +better name. The leaves have the size leaf_size = packet_len / num_parts. + +To create a bunch of packets, you need 2*num_parts stream packets. +The first part of the first stream packet is stored in leaf number 0, +the first part of the second into leaf number num_parts, the one of the +next one into leaf number 1 etc. The following part of a stream packet +is stored 2*num_packets behind the current part of the same stream packet. + +In short words: when you have a matrix with the leaves as the values, +it's a transposition in conjunction with a permutation. + +packet | leaf | stream packet, part no. +-------+---------------+------------------------ +0 | 0 | (0,0) +0 | 1 | (2,0) +. | . | . +. | . | . +0 | num_parts-1 | (2*num_parts-2,0) +0 | num_parts | (1,0) +0 | num_parts+1 | (3,0) +. | . | . +. | . | . +0 | 2*num_parts-1 | (2*num_parts-1,0) +1 | 0 | (0,1) +. | . | . +. | . | . + + +sequence of calls: +------------------ + +RAOpenCodec2() + +RAInitDecoder() + +RASetFlavor() + +RAGetFlavorProperty(0xE) + +sequence of RADecode()s + +once a RAGetFlavorProperty(0xE) after some RADecode()s + +and occasionally the following sequence: +RAGetFlavorProperty(0) +RAGetFlavorProperty(7) +which is rather pointless because they only return +cleartext audio descriptions + +RAFreeDecoder() + +RACloseCodec() + + + +RAFlush(ra_main_t *raMain, char *output_buffer, ulong *retval) +will be called when seeking +output_buffer points to the output buffer from the last +decode operation. +retval is unknown, returning always 0x18 in a specific sample +-> further investigation needed diff --git a/DOCS/OUTDATED-tech/realcodecs/streaming.txt b/DOCS/OUTDATED-tech/realcodecs/streaming.txt new file mode 100644 index 0000000000..a4af485b9b --- /dev/null +++ b/DOCS/OUTDATED-tech/realcodecs/streaming.txt @@ -0,0 +1,58 @@ +In the RV30 format, another encapsulated data layer for the video stream +has been introduced. In lack of a name I'll call them sub packets, the +normal packets which exist in RV10 I'll call - well - packets. The stream +of bytes which is put in one memory block is named block. + +The format extension has been * by wild guessing and comparing the +received data between the original viewer and the demuxer. + + + +Every packet may contain one or more sub packets, and one block may +be contained inside one or more adjacent (sub) packets. +A sub packet (fragment) starts with a small header (two letters are one byte): + + +aa(bb)[cccc{gggg}dddd{eeee}ff] + +aa: indicates the type of header + the 2MSB indicate the header type (mask C0) + C0: the [] part exists, but not () -> whole packet (not fragmented) + 00, 80: the data block is encapsulated inside multiple packets. + bb contains the sequence number, beginning with 1. + 80 indicates the last sub packet containing data for the + current block. no C0 or 40 sub packet follows until + the block has been finished with a 80 sub packet. + No packet with another stream than the current video stream + is inside the sub packet chain, at least I haven't seen + such case - the demuxer will shout in this case. + 40: [] does not exist, the meaning of bb is unknown to me + data follows to the end of the packet + mask 3F: unknown +bb: sub-seq - mask 0x7f: the sequence number of the _fragment_ + mask 0x80: unknown, seems to alternating between 00 and 80 +cccc: mask 3FFF: _total_ length of the packet + mask C000: unknown, seems to be always 4000 + when it's all 0000, it indicates value >=0x4000, you should read {gggg} + and use all 16 bits of it. dunno what happens when length>=65536... +dddd: when it's 0, {} exists (only in this case) + mask 3FFF: offset of fragment inside the whole packet. it's counted + from the beginning of the packet, except when hdr&0x80, + hten it's relative to the _end_ of the packet, so it's + equal to fragment size! + mask C000: like cccc, except the first case (always 4000) + when it's all 0000, it indicates value >=0x4000, you should read {eeee} + and use all 16 bits of it. dunno what happens when length>=65536... +ff: sequence number of the assembled (defragmented) packets, beginning with 0 + +NOTE: the demuxer should build a table of the subpacket offsets relative to the +start of whole packet, it's required by the rv20/rv30 video decoders. + + +packet header: + +ushort unknown +ulong blocksize +ushort streamid +uchar reserved +uchar flags 1=reliable, 2=keyframe diff --git a/DOCS/OUTDATED-tech/realcodecs/video-codecs.txt b/DOCS/OUTDATED-tech/realcodecs/video-codecs.txt new file mode 100644 index 0000000000..af2152061a --- /dev/null +++ b/DOCS/OUTDATED-tech/realcodecs/video-codecs.txt @@ -0,0 +1,185 @@ +The work has been based on the RV30 codec, but since RV20 has the same +interface, it might work for it as well. + + + + +error codes (the software uses redmond originated error codes) + +1. internal code (1-10) +2. result + +0 00000000 success +1 80004005 E_FAIL +2 8007000E E_OUTOFMEMORY +3,9 80004001 E_NOTIMPL +4,5 80070005 E_ACCESSDENIED +6 80004003 E_POINTER +7,10 80070057 E_INVALIDREG +8 80040FC1 (or 1FC?: CO_E_OBJISREG) - never occurred here + + + + + +I think the only relevant file is the decoder drv[23].so.6.0 +The rv[23]0 ones are just for streaming. We do this ourselves. + + +The codec consists of several functions. The relevant ones are: + +RV20toYUV420Init() +RV20toYUV420Transform() +RV20toYUV420CustomMessage() +RV20toYUV420Free() + + +The others are irrelevant (seems to me). HiveMessage doesn't manipulate +anything and is only called in the beginning. + +result=RV20toYUV420Init(struct init_data *, struct rvyuvMain **); + +struct init_data { + short constant=0xb; + short width, height; + short 0, 0, 0; + ulong format1; + long 1; + ulong format2; +}; + +format1 and format2 are stored in the .rm file's stream headers. +(format1>>16)&3 seems to be a sub-codec id/selector, at least for rv30 +it's the only difference between low and high bitrate files. + +result=RV20toYUV420Transform(char *input_stream, char *output_data, + struct transin *, struct transout *, struct rvyuvMain *); + +struct transin { + ulong length_of_input_data; + ulong null; + ulong num_sub_packets_in_block_minus_one; + ulong *sub_packets_list; + ulong another_null; + ulong timestamp_from_stream; +}; + +struct transout { + ulong flag1; // ((var_94&2!=0)&&(result==0))?1:0 + ulong flag2; // 4 LBS from var_94 + ulong zero; + ulong width, height; +}; + +The length of output_stream is 1.5*width*height (I420 planar yuv 4:2:0). +input_stream is the exact data from the data block for one frame. + +sub_packets_list is a list of num_sub_packets pairs of long values, in form: +1, 0, +1, offset_2nd, +1, offset_3rd, +1, offset_4th, +... + +where offset_* are the offsets or sub-packets relative to input_stream. + + +result=RV20toYUV420CustomMessage(ulong *msg, struct rvyuvMain *); + +Messages used by RV30: + +A message is a triplet (cmd,val,ext) of ulong. + +NOTE: +rv30 only requires the (0x24,2|3,{w,h,w,h}) message. others can be left out! +rv20 only requires the (0x11,2,0) message in rp8, before each transform call. + +(3,2,0) +returns always(?) an error, since a global variable inside the codec +(which points to a function similar to custommessage), is always NULL + +(0x11,0|1|2,0) +val=0|1: sets intern2 to val, when intern1 is non-zero + return 3 when intern1 is zero and val is 1 + else returns 0 +val=2: return intern2 +what does intern[1,2] mean? + +(0x12,...) +used by rv20, function unknown, can be ignored + +(0x1e,2|3,1) +calls a subroutine and returns the result, purpose has to be detemined + +(0x24,subcodec,{...}) +copies 4 dwords to rvyuvMain+07c: { width, height, 0, 0 } +subcodec must be 2 (low-bitrate) or 3 (high-bitrate) for rv30. +the codec type (low vs high) can be determined from 1+((format1>>16)&3) +for rv20, this call should be ignored! (makes codec crashing) + +(0x1c,a,b) - called inside transform +to be analyzed + +(105,...) +used by rv20, function unknown, can be ignored + + +structure of rvyuvMain: +----------------------- + +DWORDS (the entries are not always constant) +there are two w/h pairs at 05C. the first is the size of the +unscaled video stream, the second possibly image size + +000 1 6 3 1 +010 1 0 AEBFC0D1(magic) 0 +020 0 ptr->? 0 0 +030 0 0 ->rvyuvMain+0x050 ? +040 width height 0x17 0x479 +050 ->rvyuvMain 0x17 0x17 width +060 height width height 0 +070 0 1 0 0 +080 0 0xb w h +090 w h 0 0 +0A0 1 0xb0(w?) 0x58 0x58 +0B0 ptr->? 0 0 1 +0C0 0x32 1 0 0 +0D0 0 0 0 0 +0E0 0 0 0 0 +0F0 0 0 0 0 +100 0 0 0 0 +110 p p p p p are pointers to several function, for +120 p p p p example to the actual public functions +130 p p p p (except init, the others are some kind of +140 p p p p interfaces) +150 p 0 0 0 +160 0 0x2000 1 0 +170 0 0 0 0 +180 1 1 0 0 +190 0 0 0 0 +1A0 0 0 0 0 +1B0 1 0 ptr->? ptr->? +1C0 1 0 0 0 +1D0 0 0 0 0 +1E0 0 0 0 0 +... + + + + +Order of calls: +--------------- + +Init +(0x11,0,0) +(0x24,2,{...}) + +[ +(3,2,0)->80004001 +(0x11,1,0) +(0x1e,3,1) +Transform (internally calls (0x1c,x,y)) +(11,2,0) +] + +Free |