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