由于视频开发的需求,封装xvid c调用接口,使之优雅易用
我已经对pc camera视频流(RGB)进行尝试,编码之后传输到远程主机进行解码回放,效果不错
具体的xvid的参数可以进一步优化,这里只是提供简单的范例
1. xvid 解码
1
2
/*
3
encode.cpp
4
xvid 编码YUV数据,为进一步传输提供准备
5
6
*/
7
#ifndef _XVID_ENCODE_H
8
#define
_XVID_ENCODE_H
9
10
#include
<
xvid.h
>
11
12
struct
DecodeInfo{
13
unsigned
short
width;
14
unsigned
short
height;
15
void
(
*
after_decode)(
void
*
data,unsigned
int
size,
int
width,
int
height,
void
*
user);
16
void
*
user;
17
};
18
19
20
class
Xvid_Decoder{
21
22
public
:
23
Xvid_Decoder(){
24
}
25
bool
Open();
26
void
Close();
27
DecodeInfo
&
GetDecodeInfo(){
return
_dec_info;}
28
void
decode(
void
*
data,unsigned
int
size);
29
static
void
xvid_global_init();
30
xvid_dec_create_t
&
GetHandle(){
return
_xvid_dec_create;}
31
private
:
32
int
xvid_dec(unsigned
char
*
bitstream,
int
bs_size,unsigned
char
*
image);
33
private
:
34
DecodeInfo _dec_info;
35
void
*
_dec_handle;
36
char
_image[
1024
*
768
*
3
];
37
xvid_dec_create_t _xvid_dec_create;
38
};
39
40
#endif
41
1
2
/*
3
encode.cpp
4
xvid 编码YUV数据,为进一步传输提供准备
5
6
*/
7
#include
"
xvid_dec.h
"
8
#include
<
windows.h
>
9
10
////////////////////////////////////////////////////////////////////////
//
11
12
13
void
Xvid_Decoder::Close(){
14
int
xerr;
15
/*
Destroy the encoder instance
*/
16
xerr
=
xvid_decore(_dec_handle, XVID_ENC_DESTROY, NULL, NULL);
17
}
18
19
void
Xvid_Decoder::xvid_global_init(){
20
/*
------------------------------------------------------------------------
21
* XviD core initialization
22
*----------------------------------------------------------------------
*/
23
xvid_gbl_init_t xvid_gbl_init;
24
memset(
&
xvid_gbl_init,
0
,
sizeof
(xvid_gbl_init));
25
xvid_gbl_init.version
=
XVID_VERSION;
26
xvid_gbl_init.cpu_flags
=
XVID_CPU_FORCE;
27
/*
Initialize XviD core -- Should be done once per __process__
*/
28
xvid_global(NULL, XVID_GBL_INIT,
&
xvid_gbl_init, NULL);
29
}
30
31
bool
Xvid_Decoder::Open(){
32
int
ret;
33
34
/*
------------------------------------------------------------------------
35
* XviD encoder initialization
36
*----------------------------------------------------------------------
*/
37
int
width,height;
38
width
=
_xvid_dec_create.width ;
39
height
=
_xvid_dec_create.height;
40
memset(
&
_xvid_dec_create,
0
,
sizeof
(xvid_dec_create_t));
41
_xvid_dec_create.version
=
XVID_VERSION;
42
43
/*
Width and Height of input frames
*/
44
_xvid_dec_create.width
=
width;
45
_xvid_dec_create.height
=
height;
46
47
ret
=
xvid_decore(NULL, XVID_DEC_CREATE,
&
_xvid_dec_create, NULL);
48
_dec_handle
=
_xvid_dec_create.handle;
49
return
true
;
50
}
51
52
void
Xvid_Decoder::decode(
void
*
data,unsigned
int
size){
53
int
ret;
54
ret
=
xvid_dec((unsigned
char
*
)data,(
int
)size,(unsigned
char
*
)_image);
55
if
(ret
>
0
)
56
_dec_info.after_decode(_image,(unsigned
int
)ret,(
int
)_xvid_dec_create.width,(
int
)_xvid_dec_create.height,_dec_info.user);
57
}
58
59
/*
60
raw xvid_encode procedure
61
*/
62
int
Xvid_Decoder::xvid_dec(unsigned
char
*
bitstream,
int
bs_size,unsigned
char
*
image)
63
{
64
int
ret;
65
xvid_dec_frame_t xvid_dec_frame;
66
67
/*
Reset all structures
*/
68
memset(
&
xvid_dec_frame,
0
,
sizeof
(xvid_dec_frame_t));
69
/*
Set version
*/
70
xvid_dec_frame.version
=
XVID_VERSION;
71
//
xvid_dec_stats->version = XVID_VERSION;
72
73
/*
No general flags to set
*/
74
xvid_dec_frame.general
=
0
;
75
76
/*
Input stream
*/
77
xvid_dec_frame.bitstream
=
bitstream;
78
xvid_dec_frame.length
=
bs_size;
79
80
/*
Output frame structure
*/
81
xvid_dec_frame.output.plane[
0
]
=
image;
82
xvid_dec_frame.output.stride[
0
]
=
_xvid_dec_create.width
*
3
;
83
xvid_dec_frame.output.csp
=
XVID_CSP_BGR;
84
85
ret
=
xvid_decore(_dec_handle, XVID_DEC_DECODE,
&
xvid_dec_frame, NULL);
86
return
(ret);
87
}
88
89
90
2. xvid 编码
1
2
/*
3
encode.cpp
4
xvid 编码YUV数据,为进一步传输提供准备
5
6
*/
7
#ifndef _XVID_ENCODE_H
8
#define
_XVID_ENCODE_H
9
10
#include
<
xvid.h
>
11
#include
<
nv.h
>
12
13
14
15
struct
EncodeInfo{
16
unsigned
short
width;
17
unsigned
short
height;
18
void
(
*
after_encode)(
void
*
data,unsigned
int
size,
void
*
user);
19
void
*
user;
20
};
21
22
class
Xvid_Encoder:
public
NVObject{
23
public
:
24
Xvid_Encoder(){ _closed
=
true
;
25
}
26
bool
Open();
27
void
Close();
28
EncodeInfo
&
GetEncodeInfo(){
return
_enc_info;}
29
void
encode(
void
*
data,unsigned
int
size);
30
static
void
xvid_global_init();
31
int
xvid_enc(unsigned
char
*
image,unsigned
char
*
bitstream);
32
private
:
33
EncodeInfo _enc_info;
34
void
*
_enc_handle;
35
char
_bitstream[
1024
*
100
];
36
bool
_closed;
37
38
39
};
40
41
#endif
42
1
2
/*
3
encode.cpp
4
xvid 编码YUV数据,为进一步传输提供准备
5
6
*/
7
#include
"
encode.h
"
8
#include
<
windows.h
>
9
10
11
static
const
int
motion_presets[]
=
{
12
/*
quality 0
*/
13
0
,
14
15
/*
quality 1
*/
16
XVID_ME_ADVANCEDDIAMOND16,
17
18
/*
quality 2
*/
19
XVID_ME_ADVANCEDDIAMOND16
|
XVID_ME_HALFPELREFINE16,
20
21
/*
quality 3
*/
22
XVID_ME_ADVANCEDDIAMOND16
|
XVID_ME_HALFPELREFINE16
|
23
XVID_ME_ADVANCEDDIAMOND8
|
XVID_ME_HALFPELREFINE8,
24
25
/*
quality 4
*/
26
XVID_ME_ADVANCEDDIAMOND16
|
XVID_ME_HALFPELREFINE16
|
27
XVID_ME_ADVANCEDDIAMOND8
|
XVID_ME_HALFPELREFINE8
|
28
XVID_ME_CHROMA_PVOP
|
XVID_ME_CHROMA_BVOP,
29
30
/*
quality 5
*/
31
XVID_ME_ADVANCEDDIAMOND16
|
XVID_ME_HALFPELREFINE16
|
32
XVID_ME_ADVANCEDDIAMOND8
|
XVID_ME_HALFPELREFINE8
|
33
XVID_ME_CHROMA_PVOP
|
XVID_ME_CHROMA_BVOP,
34
35
/*
quality 6
*/
36
XVID_ME_ADVANCEDDIAMOND16
|
XVID_ME_HALFPELREFINE16
|
XVID_ME_EXTSEARCH16
|
37
XVID_ME_ADVANCEDDIAMOND8
|
XVID_ME_HALFPELREFINE8
|
XVID_ME_EXTSEARCH8
|
38
XVID_ME_CHROMA_PVOP
|
XVID_ME_CHROMA_BVOP,
39
40
};
41
#define
ME_ELEMENTS (sizeof(motion_presets)/sizeof(motion_presets[0]))
42
43
static
const
int
vop_presets[]
=
{
44
/*
quality 0
*/
45
0
,
46
47
/*
quality 1
*/
48
0
,
49
50
/*
quality 2
*/
51
XVID_VOP_HALFPEL,
52
53
/*
quality 3
*/
54
XVID_VOP_HALFPEL
|
XVID_VOP_INTER4V,
55
56
/*
quality 4
*/
57
XVID_VOP_HALFPEL
|
XVID_VOP_INTER4V,
58
59
/*
quality 5
*/
60
XVID_VOP_HALFPEL
|
XVID_VOP_INTER4V
|
61
XVID_VOP_TRELLISQUANT,
62
63
/*
quality 6
*/
64
XVID_VOP_HALFPEL
|
XVID_VOP_INTER4V
|
65
XVID_VOP_TRELLISQUANT
|
XVID_VOP_HQACPRED,
66
67
};
68
#define
VOP_ELEMENTS (sizeof(vop_presets)/sizeof(vop_presets[0]))
69
70
////////////////////////////////////////////////////////////////////////
//
71
#define
MAX_ZONES 64
72
73
/*
Maximum number of frames to encode
*/
74
#define
ABS_MAXFRAMENR 9999
75
76
static
int
ARG_STATS
=
0
;
77
static
int
ARG_DUMP
=
0
;
78
static
int
ARG_LUMIMASKING
=
0
;
79
static
int
ARG_BITRATE
=
0
;
80
static
int
ARG_SINGLE
=
0
;
81
static
char
*
ARG_PASS1
=
0
;
82
static
char
*
ARG_PASS2
=
0
;
83
static
int
ARG_QUALITY
=
ME_ELEMENTS
-
1
;
84
static
float
ARG_FRAMERATE
=
25.00f
;
85
static
int
ARG_MAXFRAMENR
=
ABS_MAXFRAMENR;
86
static
int
ARG_MAXKEYINTERVAL
=
0
;
87
static
char
*
ARG_INPUTFILE
=
NULL;
88
static
int
ARG_INPUTTYPE
=
0
;
89
static
int
ARG_SAVEMPEGSTREAM
=
0
;
90
static
int
ARG_SAVEINDIVIDUAL
=
0
;
91
static
char
*
ARG_OUTPUTFILE
=
NULL;
92
93
static
int
ARG_BQRATIO
=
150
;
94
static
int
ARG_BQOFFSET
=
100
;
95
static
int
ARG_MAXBFRAMES
=
0
;
96
static
int
ARG_PACKED
=
0
;
97
98
static
int
ARG_VOPDEBUG
=
0
;
99
static
int
ARG_GMC
=
0
;
100
static
int
ARG_INTERLACING
=
0
;
101
static
int
ARG_QPEL
=
0
;
102
static
int
ARG_CLOSED_GOP
=
0
;
103
104
#ifndef READ_PNM
105
#define
IMAGE_SIZE(x,y) ((x)*(y)*3/2)
106
#else
107
#define
IMAGE_SIZE(x,y) ((x)*(y)*3)
108
#endif
109
110
#define
MAX(A,B) ( ((A)>(B)) ? (A) : (B) )
111
#define
SMALL_EPS (1e-10)
112
113
#define
SWAP(a) ( (((a)&0x000000ff)<<24) | (((a)&0x0000ff00)<<8) | \
114
(((a)
&
0x00ff0000
)
>>
8
)
|
(((a)
&
0xff000000
)
>>
24
) )
115
116
117
////////////////////////////////////////////////////////////////////////
//
118
119
120
void
Xvid_Encoder::Close(){
121
int
xerr;
122
NVMutexLock
lock
(_lock);
123
124
_closed
=
true
;
125
/*
Destroy the encoder instance
*/
126
xerr
=
xvid_encore(_enc_handle, XVID_ENC_DESTROY, NULL, NULL);
127
128
}
129
130
void
Xvid_Encoder::xvid_global_init(){
131
/*
------------------------------------------------------------------------
132
* XviD core initialization
133
*----------------------------------------------------------------------
*/
134
xvid_gbl_init_t xvid_gbl_init;
135
memset(
&
xvid_gbl_init,
0
,
sizeof
(xvid_gbl_init));
136
xvid_gbl_init.version
=
XVID_VERSION;
137
xvid_gbl_init.cpu_flags
=
XVID_CPU_FORCE;
138
/*
Initialize XviD core -- Should be done once per __process__
*/
139
xvid_global(NULL, XVID_GBL_INIT,
&
xvid_gbl_init, NULL);
140
}
141
142
bool
Xvid_Encoder::Open(){
143
int
xerr;
144
xvid_enc_create_t xvid_enc_create;
145
_closed
=
false
;
146
/*
------------------------------------------------------------------------
147
* XviD encoder initialization
148
*----------------------------------------------------------------------
*/
149
memset(
&
xvid_enc_create,
0
,
sizeof
(xvid_enc_create));
150
xvid_enc_create.version
=
XVID_VERSION;
151
152
/*
Width and Height of input frames
*/
153
xvid_enc_create.width
=
GetEncodeInfo().width;
154
xvid_enc_create.height
=
GetEncodeInfo().height;
155
xvid_enc_create.profile
=
XVID_PROFILE_AS_L4;
156
157
/*
init plugins
*/
158
/*
159
xvid_enc_create.zones = ZONES;
160
xvid_enc_create.num_zones = NUM_ZONES;
161
162
xvid_enc_create.plugins = plugins;
163
xvid_enc_create.num_plugins = 0;
164
*/
165
166
167
/*
No fancy thread tests
*/
168
xvid_enc_create.num_threads
=
0
;
169
170
/*
Frame rate - Do some quick float fps = fincr/fbase hack
*/
171
xvid_enc_create.fincr
=
1
;
172
xvid_enc_create.fbase
=
(
int
)
10
;
173
/*
Maximum key frame interval
*/
174
xvid_enc_create.max_key_interval
=
(
int
)
-
1
;
//
--default 10s
175
/*
Bframes settings
*/
176
xvid_enc_create.max_bframes
=
ARG_MAXBFRAMES;
177
xvid_enc_create.bquant_ratio
=
ARG_BQRATIO;
178
xvid_enc_create.bquant_offset
=
ARG_BQOFFSET;
179
180
/*
Dropping ratio frame -- we don't need that
*/
181
xvid_enc_create.frame_drop_ratio
=
0
;
182
/*
Global encoder options
*/
183
xvid_enc_create.global
=
0
;
184
185
if
(ARG_PACKED)
186
xvid_enc_create.global
|=
XVID_GLOBAL_PACKED;
187
188
if
(ARG_CLOSED_GOP)
189
xvid_enc_create.global
|=
XVID_GLOBAL_CLOSED_GOP;
190
191
if
(ARG_STATS)
192
xvid_enc_create.global
|=
XVID_GLOBAL_EXTRASTATS_ENABLE;
193
194
/*
I use a small value here, since will not encode whole movies, but short clips
*/
195
xerr
=
xvid_encore(NULL, XVID_ENC_CREATE,
&
xvid_enc_create, NULL);
196
_enc_handle
=
xvid_enc_create.handle;
197
return
true
;
198
}
199
200
void
Xvid_Encoder::encode(
void
*
data,unsigned
int
size){
201
int
ret;
202
_lock.Lock();
203
if
( _closed ){
204
_lock.Unlock();
205
return
;
206
}
207
ret
=
xvid_enc((unsigned
char
*
)data,(unsigned
char
*
)_bitstream);
208
_lock.Unlock();
209
if
(ret
>
0
)
210
_enc_info.after_encode(_bitstream,(unsigned
int
)ret,_enc_info.user);
211
212
}
213
214
/*
215
raw xvid_encode procedure
216
*/
217
int
Xvid_Encoder::xvid_enc(unsigned
char
*
image,unsigned
char
*
bitstream)
218
{
219
int
ret;
220
xvid_enc_frame_t xvid_enc_frame;
221
xvid_enc_stats_t xvid_enc_stats;
222
223
/*
Version for the frame and the stats
*/
224
memset(
&
xvid_enc_frame,
0
,
sizeof
(xvid_enc_frame));
225
xvid_enc_frame.version
=
XVID_VERSION;
226
227
memset(
&
xvid_enc_stats,
0
,
sizeof
(xvid_enc_stats));
228
xvid_enc_stats.version
=
XVID_VERSION;
229
230
/*
Bind output buffer
*/
231
xvid_enc_frame.bitstream
=
bitstream;
232
xvid_enc_frame.length
=
-
1
;
233
234
/*
Initialize input image fields
*/
235
xvid_enc_frame.input.plane[
0
]
=
image;
236
xvid_enc_frame.input.csp
=
XVID_CSP_BGR;
237
xvid_enc_frame.input.stride[
0
]
=
_enc_info.width
*
3
;
238
239
240
/*
Set up core's general features
*/
241
xvid_enc_frame.vol_flags
=
0
;
242
243
/*
Set up core's general features
*/
244
xvid_enc_frame.vop_flags
=
vop_presets[ARG_QUALITY
-
2
];
245
246
/*
Frame type -- let core decide for us
*/
247
xvid_enc_frame.type
=
XVID_TYPE_AUTO;
248
249
/*
Force the right quantizer -- It is internally managed by RC plugins
*/
250
xvid_enc_frame.quant
=
0
;
251
252
/*
Set up motion estimation flags
*/
253
xvid_enc_frame.motion
=
motion_presets[ARG_QUALITY
-
2
];
254
255
/*
We don't use special matrices
*/
256
xvid_enc_frame.quant_intra_matrix
=
NULL;
257
xvid_enc_frame.quant_inter_matrix
=
NULL;
258
259
/*
Encode the frame
*/
260
ret
=
xvid_encore(_enc_handle, XVID_ENC_ENCODE,
&
xvid_enc_frame,NULL);
261
//
&xvid_enc_stats);
262
//
--判别是否是关键帧
263
//
*key = (xvid_enc_frame.out_flags & XVID_KEYFRAME);
264
//
*stats_type = xvid_enc_stats.type;
265
//
*stats_quant = xvid_enc_stats.quant;
266
//
*stats_length = xvid_enc_stats.length;
267
//
sse[0] = xvid_enc_stats.sse_y;
268
//
sse[1] = xvid_enc_stats.sse_u;
269
//
sse[2] = xvid_enc_stats.sse_v;
270
271
return
(ret);
272
}
273
274
275