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 char *buffer=NULL;
|
|
34 static int frameno=0;
|
|
35
|
|
36 extern char* encode_name;
|
|
37 extern char* encode_index_name;
|
|
38
|
|
39 static uint32_t
|
|
40 draw_slice(uint8_t *src[], uint32_t slice_num)
|
|
41 {
|
|
42 uint8_t *d;
|
|
43
|
|
44 // copy Y
|
|
45 d=image;
|
|
46 memcpy(d+(slice_num<<4)*image_width,src[0],image_width*16);
|
|
47 // copy U
|
|
48 d+=image_width*image_height;
|
|
49 memcpy(d+(slice_num<<2)*image_width,src[1],image_width*4);
|
|
50 // copy V
|
|
51 d+=image_width*image_height/4;
|
|
52 memcpy(d+(slice_num<<2)*image_width,src[2],image_width*4);
|
|
53
|
|
54 return 0;
|
|
55 }
|
|
56
|
|
57 static uint32_t
|
|
58 draw_frame(uint8_t *src[])
|
|
59 {
|
|
60 uint8_t *d;
|
|
61
|
|
62 // copy Y
|
|
63 d=image;
|
|
64 memcpy(d,src[0],image_width*image_height);
|
|
65 // copy U
|
|
66 d+=image_width*image_height;
|
|
67 memcpy(d,src[1],image_width*image_height/4);
|
|
68 // copy V
|
|
69 d+=image_width*image_height/4;
|
|
70 memcpy(d,src[2],image_width*image_height/4);
|
|
71
|
|
72 return 0;
|
|
73 }
|
|
74
|
|
75 typedef unsigned int DWORD;
|
|
76
|
|
77 typedef struct
|
|
78 {
|
|
79 DWORD ckid;
|
|
80 DWORD dwFlags;
|
|
81 DWORD dwChunkOffset; // Position of chunk
|
|
82 DWORD dwChunkLength; // Length of chunk
|
|
83 } AVIINDEXENTRY;
|
|
84
|
|
85 static void
|
|
86 flip_page(void)
|
|
87 {
|
|
88
|
|
89 // we are rady to encode this frame
|
|
90 ENC_FRAME enc_frame;
|
|
91 ENC_RESULT enc_result;
|
|
92
|
|
93 if(++frameno<10) return;
|
|
94
|
|
95 enc_frame.bmp=image;
|
|
96 enc_frame.bitstream=buffer;
|
|
97 enc_frame.length=0;
|
|
98 encore(0x123,0,&enc_frame,&enc_result);
|
|
99
|
|
100 printf("coded length: %d \n",enc_frame.length);
|
|
101
|
|
102 if(encode_name){
|
|
103 AVIINDEXENTRY i;
|
|
104 FILE *file;
|
|
105 i.ckid=('c'<<24)|('d'<<16)|('0'<<8)|'0'; // "00dc"
|
|
106 i.dwFlags=enc_result.isKeyFrame?0x10:0;
|
|
107 i.dwChunkLength=enc_frame.length;
|
|
108 // Write AVI chunk:
|
|
109 if((file=fopen(encode_name,"ab"))){
|
|
110 unsigned char zerobyte=0;
|
|
111 i.dwChunkOffset=ftell(file);
|
|
112 fwrite(&i.ckid,4,1,file);
|
|
113 fwrite(&enc_frame.length,4,1,file);
|
|
114 fwrite(buffer,enc_frame.length,1,file);
|
|
115 if(enc_frame.length&1) fwrite(&zerobyte,1,1,file); // padding
|
|
116 fclose(file);
|
|
117 }
|
|
118 // Write AVI index:
|
|
119 if(encode_index_name && (file=fopen(encode_index_name,"ab"))){
|
|
120 fwrite(&i,sizeof(i),1,file);
|
|
121 fclose(file);
|
|
122 }
|
|
123 }
|
|
124
|
|
125
|
|
126 }
|
|
127
|
|
128 static uint32_t
|
|
129 query_format(uint32_t format)
|
|
130 {
|
|
131 switch(format){
|
|
132 case IMGFMT_YV12:
|
|
133 // case IMGFMT_YUY2:
|
|
134 // case IMGFMT_RGB|24:
|
|
135 // case IMGFMT_BGR|24:
|
|
136 return 1;
|
|
137 }
|
|
138 return 0;
|
|
139 }
|
|
140
|
|
141 static uint32_t
|
|
142 init(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t fullscreen, char *title, uint32_t format)
|
|
143 {
|
|
144 uint32_t frame_size;
|
|
145 ENC_PARAM enc_param;
|
|
146
|
|
147 buffer=malloc(0x100000);
|
|
148 if(!buffer) return -1;
|
|
149
|
|
150 // file = fopen("encoded.odvx","wb");
|
|
151 // if(!file) return -1;
|
|
152
|
|
153 frame_size=width*height+width*height/2;
|
|
154 image_width=width;
|
|
155 image_height=height;
|
|
156 image=malloc(frame_size);
|
|
157
|
|
158 //clear the buffer
|
|
159 memset(image,0x80,frame_size);
|
|
160
|
|
161 // encoding parameters:
|
|
162 enc_param.framerate=25.0;
|
|
163 enc_param.bitrate=400000; //780000;
|
|
164 enc_param.rc_period=300;
|
|
165 enc_param.max_quantizer=15;
|
|
166 enc_param.min_quantizer=1;
|
|
167 enc_param.search_range=128;
|
|
168
|
|
169 // init codec:
|
|
170 enc_param.x_dim=width;
|
|
171 enc_param.y_dim=height;
|
|
172 enc_param.flip=2; // 0=RGB 1=flippedRGB 2=planarYUV format
|
|
173 encore(0x123,ENC_OPT_INIT,&enc_param,NULL);
|
|
174
|
|
175 return 0;
|
|
176 }
|
|
177
|
|
178 static const vo_info_t*
|
|
179 get_info(void)
|
|
180 {
|
|
181 return &vo_info;
|
|
182 }
|
|
183
|