1
|
1 /*
|
|
2 * OpenDivX AVI file writer
|
|
3 */
|
|
4
|
|
5 #include <stdio.h>
|
|
6 #include <stdlib.h>
|
|
7 #include <string.h>
|
|
8
|
|
9 #include "config.h"
|
|
10 #include "video_out.h"
|
|
11 #include "video_out_internal.h"
|
|
12
|
|
13 LIBVO_EXTERN(odivx)
|
|
14
|
|
15 #include <sys/ioctl.h>
|
|
16 #include <unistd.h>
|
|
17 #include <fcntl.h>
|
|
18 #include <sys/mman.h>
|
|
19
|
|
20 #include "../encore/encore.h"
|
|
21
|
354
|
22 #include "fastmemcpy.h"
|
350
|
23
|
1
|
24 static vo_info_t vo_info =
|
|
25 {
|
|
26 "OpenDivX AVI File writer",
|
|
27 "odivx",
|
|
28 "Arpad Gereoffy <arpi@esp-team.scene.hu>",
|
|
29 ""
|
|
30 };
|
|
31
|
|
32 static uint8_t *image=NULL;
|
|
33 static int image_width=0;
|
|
34 static int image_height=0;
|
|
35 static unsigned int image_format=0;
|
|
36 static char *buffer=NULL;
|
|
37 static int frameno=0;
|
|
38
|
|
39 extern char* encode_name;
|
|
40 extern char* encode_index_name;
|
|
41
|
|
42 //static uint32_t draw_slice(uint8_t *src[], uint32_t slice_num)
|
|
43 static uint32_t draw_slice(uint8_t *src[], int stride[], int w,int h,int x,int y)
|
|
44 {
|
|
45 uint8_t *s;
|
|
46 uint8_t *d;
|
|
47 int i;
|
|
48 int dstride=image_width;
|
|
49
|
|
50 // copy Y
|
|
51 d=image+dstride*y+x;
|
|
52 s=src[0];
|
|
53 for(i=0;i<h;i++){
|
|
54 memcpy(d,s,w);
|
|
55 s+=stride[0];
|
|
56 d+=dstride;
|
|
57 }
|
|
58
|
|
59 w/=2;h/=2;x/=2;y/=2; dstride/=2;
|
|
60
|
|
61 // copy U
|
|
62 d=image+image_width*image_height + dstride*y+x;
|
|
63 s=src[1];
|
|
64 for(i=0;i<h;i++){
|
|
65 memcpy(d,s,w);
|
|
66 s+=stride[1];
|
|
67 d+=dstride;
|
|
68 }
|
|
69
|
|
70 // copy V
|
|
71 d=image+image_width*image_height +image_width*image_height/4 + dstride*y+x;
|
|
72 s=src[2];
|
|
73 for(i=0;i<h;i++){
|
|
74 memcpy(d,s,w);
|
|
75 s+=stride[2];
|
|
76 d+=dstride;
|
|
77 }
|
|
78
|
|
79 return 0;
|
|
80 }
|
|
81
|
|
82 static uint32_t
|
|
83 draw_frame(uint8_t *src[])
|
|
84 {
|
|
85 uint8_t *d=image;
|
|
86
|
|
87 switch(image_format){
|
|
88 case IMGFMT_YV12:
|
|
89 // copy Y
|
|
90 memcpy(d,src[0],image_width*image_height);
|
|
91 // copy U
|
|
92 d+=image_width*image_height;
|
|
93 memcpy(d,src[1],image_width*image_height/4);
|
|
94 // copy V
|
|
95 d+=image_width*image_height/4;
|
|
96 memcpy(d,src[2],image_width*image_height/4);
|
|
97 break;
|
80
|
98 case IMGFMT_YUY2: {
|
|
99 uint8_t *dY=image;
|
|
100 uint8_t *dU=image+image_width*image_height;
|
|
101 uint8_t *dV=dU+image_width*image_height/4;
|
|
102 uint8_t *s=src[0];
|
|
103 int y;
|
|
104 for(y=0;y<image_height;y+=2){
|
|
105 uint8_t *e=s+image_width*2;
|
|
106 while(s<e){
|
|
107 *dY++=s[0];
|
|
108 *dU++=s[1];
|
|
109 *dY++=s[2];
|
|
110 *dV++=s[3];
|
|
111 s+=4;
|
|
112 }
|
|
113 e=s+image_width*2;
|
|
114 while(s<e){
|
|
115 *dY++=s[0];
|
|
116 *dY++=s[2];
|
|
117 s+=4;
|
|
118 }
|
|
119 }
|
|
120
|
|
121 // case IMGFMT_BGR|24:
|
|
122 // memcpy(d,src[0],image_width*image_height*2);
|
1
|
123 break;
|
|
124 }
|
80
|
125 }
|
1
|
126
|
|
127 return 0;
|
|
128 }
|
|
129
|
|
130 typedef unsigned int DWORD;
|
|
131
|
|
132 typedef struct
|
|
133 {
|
|
134 DWORD ckid;
|
|
135 DWORD dwFlags;
|
|
136 DWORD dwChunkOffset; // Position of chunk
|
|
137 DWORD dwChunkLength; // Length of chunk
|
|
138 } AVIINDEXENTRY;
|
|
139
|
|
140 static void
|
|
141 flip_page(void)
|
|
142 {
|
|
143
|
|
144 // we are rady to encode this frame
|
|
145 ENC_FRAME enc_frame;
|
|
146 ENC_RESULT enc_result;
|
|
147
|
|
148 if(++frameno<10) return;
|
|
149
|
80
|
150 enc_frame.image=image;
|
1
|
151 enc_frame.bitstream=buffer;
|
|
152 enc_frame.length=0;
|
|
153 encore(0x123,0,&enc_frame,&enc_result);
|
|
154
|
612
|
155 printf("coded length: %ld \n",enc_frame.length);
|
1
|
156
|
|
157 if(encode_name){
|
|
158 AVIINDEXENTRY i;
|
|
159 FILE *file;
|
|
160 i.ckid=('c'<<24)|('d'<<16)|('0'<<8)|'0'; // "00dc"
|
|
161 i.dwFlags=enc_result.isKeyFrame?0x10:0;
|
|
162 i.dwChunkLength=enc_frame.length;
|
|
163 // Write AVI chunk:
|
|
164 if((file=fopen(encode_name,"ab"))){
|
|
165 unsigned char zerobyte=0;
|
|
166 i.dwChunkOffset=ftell(file);
|
|
167 fwrite(&i.ckid,4,1,file);
|
|
168 fwrite(&enc_frame.length,4,1,file);
|
|
169 fwrite(buffer,enc_frame.length,1,file);
|
|
170 if(enc_frame.length&1) fwrite(&zerobyte,1,1,file); // padding
|
|
171 fclose(file);
|
|
172 }
|
|
173 // Write AVI index:
|
|
174 if(encode_index_name && (file=fopen(encode_index_name,"ab"))){
|
|
175 fwrite(&i,sizeof(i),1,file);
|
|
176 fclose(file);
|
|
177 }
|
|
178 }
|
|
179
|
|
180
|
|
181 }
|
|
182
|
|
183 static uint32_t
|
|
184 query_format(uint32_t format)
|
|
185 {
|
|
186 switch(format){
|
|
187 case IMGFMT_YV12:
|
80
|
188 case IMGFMT_YUY2:
|
|
189 // case IMGFMT_BGR|24:
|
1
|
190 return 1;
|
|
191 }
|
|
192 return 0;
|
|
193 }
|
|
194
|
|
195 extern int encode_bitrate;
|
|
196
|
|
197 static uint32_t
|
|
198 init(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t fullscreen, char *title, uint32_t format)
|
|
199 {
|
|
200 uint32_t frame_size;
|
|
201 ENC_PARAM enc_param;
|
|
202
|
|
203 // file = fopen("encoded.odvx","wb");
|
|
204 // if(!file) return -1;
|
|
205
|
|
206 switch(format){
|
|
207 case IMGFMT_YV12:
|
|
208 frame_size=width*height+width*height/2;
|
80
|
209 // enc_param.flip=2; // 0=RGB 1=flippedRGB 2=planarYUV format
|
1
|
210 break;
|
80
|
211 case IMGFMT_YUY2:
|
|
212 // case IMGFMT_BGR|24:
|
|
213 // enc_param.flip=0; // 0=RGB 1=flippedRGB 2=planarYUV format
|
|
214 // frame_size=width*height*2;
|
|
215 frame_size=width*height+width*height/2;
|
1
|
216 break;
|
|
217 default: return -1; // invalid format
|
|
218 }
|
|
219
|
|
220 enc_param.x_dim=width;
|
|
221 enc_param.y_dim=height;
|
|
222
|
|
223 image_width=width;
|
|
224 image_height=height;
|
|
225 image_format=format;
|
|
226 image=malloc(frame_size);
|
|
227
|
|
228 //clear the buffer
|
|
229 memset(image,0x80,frame_size);
|
|
230
|
|
231 // buffer for encoded video data:
|
|
232 buffer=malloc(0x100000);
|
|
233 if(!buffer) return -1;
|
|
234
|
|
235 // encoding parameters:
|
|
236 enc_param.framerate=25.0;
|
|
237 enc_param.bitrate=encode_bitrate?encode_bitrate:780000;
|
|
238 enc_param.rc_period=300;
|
|
239 enc_param.max_quantizer=15;
|
|
240 enc_param.min_quantizer=1;
|
|
241 enc_param.search_range=128;
|
|
242
|
|
243 // init codec:
|
|
244 encore(0x123,ENC_OPT_INIT,&enc_param,NULL);
|
|
245
|
|
246 return 0;
|
|
247 }
|
|
248
|
|
249 static const vo_info_t*
|
|
250 get_info(void)
|
|
251 {
|
|
252 return &vo_info;
|
|
253 }
|
|
254
|
|
255 static void
|
|
256 uninit(void)
|
|
257 {
|
|
258 }
|
|
259
|
|
260
|
|
261
|
31
|
262 static void check_events(void)
|
|
263 {
|
|
264 }
|
|
265
|
|
266
|