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;
|
|
96 // case IMGFMT_YUY2:
|
|
97 case IMGFMT_BGR|24:
|
|
98 memcpy(d,src[0],image_width*image_height*3);
|
|
99 break;
|
|
100 }
|
|
101
|
|
102 return 0;
|
|
103 }
|
|
104
|
|
105 typedef unsigned int DWORD;
|
|
106
|
|
107 typedef struct
|
|
108 {
|
|
109 DWORD ckid;
|
|
110 DWORD dwFlags;
|
|
111 DWORD dwChunkOffset; // Position of chunk
|
|
112 DWORD dwChunkLength; // Length of chunk
|
|
113 } AVIINDEXENTRY;
|
|
114
|
|
115 static void
|
|
116 flip_page(void)
|
|
117 {
|
|
118
|
|
119 // we are rady to encode this frame
|
|
120 ENC_FRAME enc_frame;
|
|
121 ENC_RESULT enc_result;
|
|
122
|
|
123 if(++frameno<10) return;
|
|
124
|
|
125 enc_frame.bmp=image;
|
|
126 enc_frame.bitstream=buffer;
|
|
127 enc_frame.length=0;
|
|
128 encore(0x123,0,&enc_frame,&enc_result);
|
|
129
|
|
130 printf("coded length: %d \n",enc_frame.length);
|
|
131
|
|
132 if(encode_name){
|
|
133 AVIINDEXENTRY i;
|
|
134 FILE *file;
|
|
135 i.ckid=('c'<<24)|('d'<<16)|('0'<<8)|'0'; // "00dc"
|
|
136 i.dwFlags=enc_result.isKeyFrame?0x10:0;
|
|
137 i.dwChunkLength=enc_frame.length;
|
|
138 // Write AVI chunk:
|
|
139 if((file=fopen(encode_name,"ab"))){
|
|
140 unsigned char zerobyte=0;
|
|
141 i.dwChunkOffset=ftell(file);
|
|
142 fwrite(&i.ckid,4,1,file);
|
|
143 fwrite(&enc_frame.length,4,1,file);
|
|
144 fwrite(buffer,enc_frame.length,1,file);
|
|
145 if(enc_frame.length&1) fwrite(&zerobyte,1,1,file); // padding
|
|
146 fclose(file);
|
|
147 }
|
|
148 // Write AVI index:
|
|
149 if(encode_index_name && (file=fopen(encode_index_name,"ab"))){
|
|
150 fwrite(&i,sizeof(i),1,file);
|
|
151 fclose(file);
|
|
152 }
|
|
153 }
|
|
154
|
|
155
|
|
156 }
|
|
157
|
|
158 static uint32_t
|
|
159 query_format(uint32_t format)
|
|
160 {
|
|
161 switch(format){
|
|
162 case IMGFMT_YV12:
|
|
163 // case IMGFMT_YUY2:
|
|
164 case IMGFMT_BGR|24:
|
|
165 return 1;
|
|
166 }
|
|
167 return 0;
|
|
168 }
|
|
169
|
|
170 extern int encode_bitrate;
|
|
171
|
|
172 static uint32_t
|
|
173 init(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t fullscreen, char *title, uint32_t format)
|
|
174 {
|
|
175 uint32_t frame_size;
|
|
176 ENC_PARAM enc_param;
|
|
177
|
|
178 // file = fopen("encoded.odvx","wb");
|
|
179 // if(!file) return -1;
|
|
180
|
|
181 switch(format){
|
|
182 case IMGFMT_YV12:
|
|
183 frame_size=width*height+width*height/2;
|
|
184 enc_param.flip=2; // 0=RGB 1=flippedRGB 2=planarYUV format
|
|
185 break;
|
|
186 case IMGFMT_BGR|24:
|
|
187 enc_param.flip=0; // 0=RGB 1=flippedRGB 2=planarYUV format
|
|
188 frame_size=width*height*3;
|
|
189 break;
|
|
190 default: return -1; // invalid format
|
|
191 }
|
|
192
|
|
193 enc_param.x_dim=width;
|
|
194 enc_param.y_dim=height;
|
|
195
|
|
196 image_width=width;
|
|
197 image_height=height;
|
|
198 image_format=format;
|
|
199 image=malloc(frame_size);
|
|
200
|
|
201 //clear the buffer
|
|
202 memset(image,0x80,frame_size);
|
|
203
|
|
204 // buffer for encoded video data:
|
|
205 buffer=malloc(0x100000);
|
|
206 if(!buffer) return -1;
|
|
207
|
|
208 // encoding parameters:
|
|
209 enc_param.framerate=25.0;
|
|
210 enc_param.bitrate=encode_bitrate?encode_bitrate:780000;
|
|
211 enc_param.rc_period=300;
|
|
212 enc_param.max_quantizer=15;
|
|
213 enc_param.min_quantizer=1;
|
|
214 enc_param.search_range=128;
|
|
215
|
|
216 // init codec:
|
|
217 encore(0x123,ENC_OPT_INIT,&enc_param,NULL);
|
|
218
|
|
219 return 0;
|
|
220 }
|
|
221
|
|
222 static const vo_info_t*
|
|
223 get_info(void)
|
|
224 {
|
|
225 return &vo_info;
|
|
226 }
|
|
227
|
|
228 static void
|
|
229 uninit(void)
|
|
230 {
|
|
231 }
|
|
232
|
|
233
|
|
234
|