mirror of https://github.com/mpv-player/mpv
178 lines
3.6 KiB
Plaintext
178 lines
3.6 KiB
Plaintext
|
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 occured 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;
|
||
|
};
|
||
|
|
||
|
|
||
|
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;
|
||
|
struct transin1 *ptr;
|
||
|
ulong another_null;
|
||
|
ulong timestamp_from_stream;
|
||
|
};
|
||
|
|
||
|
struct transin1 {
|
||
|
ulong 1, 0;
|
||
|
// ... more data? the codec's behaviour changed sometimes
|
||
|
// when I changed the data following the first to ulongs
|
||
|
// i.e. it crashed. I've set it to 0
|
||
|
// TODO: understand (the purpose of) these values
|
||
|
// often contains 0x28, 0x19
|
||
|
// sometimes 0x28, 0x11
|
||
|
// sometimes even other data (e.g. pointers)
|
||
|
// a breakpoint didn't reveal a read operation. weird.
|
||
|
};
|
||
|
|
||
|
|
||
|
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.
|
||
|
input_stream is the exact data from the data block for one frame.
|
||
|
|
||
|
|
||
|
|
||
|
result=RV20toYUV420CustomMessage(ulong *msg, struct rvyuvMain *);
|
||
|
|
||
|
Messages used by RV30:
|
||
|
|
||
|
A message is a triplet (cmd,val,ext) of ulong.
|
||
|
|
||
|
(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?
|
||
|
|
||
|
(0x1e,2|3,1)
|
||
|
calls a subroutine and returns the result, purpose has to be detemined
|
||
|
|
||
|
(0x24,2,{...})
|
||
|
copies 4 dwords to rvyuvMain+07c: { width, height, 0, 0 }
|
||
|
|
||
|
(0x1c,a,b) - called inside transform
|
||
|
to be analyzed
|
||
|
|
||
|
|
||
|
|
||
|
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
|
||
|
|
||
|
|