initial commit
[goodguy/history.git] / cinelerra-5.0 / quicktime / yv12.c
1 #include "colormodels.h"
2 #include "funcprotos.h"
3 #include "quicktime.h"
4 #include "workarounds.h"
5 #include "yv12.h"
6
7 #include <stdlib.h>
8
9 #ifndef CLAMP
10 #define CLAMP(x, low, high)  (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
11 #endif
12
13 typedef struct
14 {
15         cmodel_yuv_t yuv_table;
16         int coded_w, coded_h;
17         unsigned char *work_buffer;
18         int initialized;
19 } quicktime_yv12_codec_t;
20
21 static void delete_codec(quicktime_video_map_t *vtrack)
22 {
23         quicktime_yv12_codec_t *codec;
24
25         codec = ((quicktime_codec_t*)vtrack->codec)->priv;
26         free(codec->work_buffer);
27         free(codec);
28 }
29
30 static int reads_colormodel(quicktime_t *file, 
31                 int colormodel, 
32                 int track)
33 {
34         return (colormodel == BC_RGB888 ||
35                 colormodel == BC_YUV888 ||
36                 colormodel == BC_YUV420P);
37 }
38
39 static int writes_colormodel(quicktime_t *file, 
40                 int colormodel, 
41                 int track)
42 {
43         return (colormodel == BC_YUV420P);
44 }
45
46 static void initialize(quicktime_video_map_t *vtrack)
47 {
48         quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
49         quicktime_yv12_codec_t *codec = codec_base->priv;
50         if(!codec->initialized)
51         {
52 /* Init private items */
53                 codec->coded_w = (int)(vtrack->track->tkhd.track_width / 2);
54                 codec->coded_w *= 2;
55                 codec->coded_h = (int)(vtrack->track->tkhd.track_height / 2);
56                 codec->coded_h *= 2;
57                 cmodel_init_yuv(&codec->yuv_table);
58                 codec->work_buffer = malloc(codec->coded_w * codec->coded_h + 
59                         codec->coded_w * codec->coded_h / 2);
60                 codec->initialized = 1;
61         }
62 }
63
64 static int decode(quicktime_t *file, unsigned char **row_pointers, int track)
65 {
66         quicktime_video_map_t *vtrack = &(file->vtracks[track]);
67         quicktime_yv12_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
68         int width = vtrack->track->tkhd.track_width;
69         int height = vtrack->track->tkhd.track_height;
70         int64_t y_size, u_size, v_size, bytes;
71         int result = 0;
72         initialize(vtrack);
73
74         y_size = codec->coded_h * codec->coded_w;
75         u_size = codec->coded_h * codec->coded_w / 4;
76         v_size = codec->coded_h * codec->coded_w / 4;
77
78         quicktime_set_video_position(file, vtrack->current_position, track);
79         bytes = quicktime_frame_size(file, vtrack->current_position, track);
80
81
82         if(file->color_model == BC_YUV420P && 
83                         file->in_x == 0 && 
84                         file->in_y == 0 && 
85                         file->in_w == width &&
86                         file->in_h == height &&
87                         file->out_w == width &&
88                         file->out_h == height)
89         {
90                 result = !quicktime_read_data(file, (char*)row_pointers[0], y_size);
91                 result = !quicktime_read_data(file, (char*)row_pointers[1], u_size);
92                 result = !quicktime_read_data(file, (char*)row_pointers[2], v_size);
93         }
94         else
95         {
96                 result = !quicktime_read_data(file, (char*)codec->work_buffer, bytes);
97                 cmodel_transfer(row_pointers, 
98                         0,
99                         row_pointers[0],
100                         row_pointers[1],
101                         row_pointers[2],
102                         codec->work_buffer,
103                         codec->work_buffer + y_size,
104                         codec->work_buffer + y_size + u_size,
105                         file->in_x, 
106                         file->in_y, 
107                         file->in_w, 
108                         file->in_h,
109                         0, 
110                         0, 
111                         file->out_w, 
112                         file->out_h,
113                         BC_YUV420P, 
114                         file->color_model,
115                         0,
116                         codec->coded_w,
117                         file->out_w);
118         }
119
120         return result;
121 }
122
123 static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
124 {
125 //      int64_t offset = quicktime_position(file);
126         quicktime_video_map_t *vtrack = &(file->vtracks[track]);
127         quicktime_yv12_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
128         quicktime_trak_t *trak = vtrack->track;
129         int result = 0;
130         int width = vtrack->track->tkhd.track_width;
131         int height = vtrack->track->tkhd.track_height;
132         int64_t y_size, u_size, v_size, bytes;
133         quicktime_atom_t chunk_atom;
134         initialize(vtrack);
135
136         y_size = codec->coded_h * codec->coded_w;
137         u_size = codec->coded_h * codec->coded_w / 4;
138         v_size = codec->coded_h * codec->coded_w / 4;
139         bytes = quicktime_add3(y_size, u_size, v_size);
140
141         quicktime_write_chunk_header(file, trak, &chunk_atom);
142         if(file->color_model == BC_YUV420P)
143         {
144                 result = !quicktime_write_data(file, (char*)row_pointers[0], y_size);
145                 if(!result) result = !quicktime_write_data(file, (char*)row_pointers[1], u_size);
146                 if(!result) result = !quicktime_write_data(file, (char*)row_pointers[2], v_size);
147         }
148         else
149         {
150                 cmodel_transfer(0, 
151                         row_pointers,
152                         codec->work_buffer,
153                         codec->work_buffer + y_size,
154                         codec->work_buffer + y_size + u_size,
155                         row_pointers[0],
156                         row_pointers[1],
157                         row_pointers[2],
158                         0, 
159                         0, 
160                         width, 
161                         height,
162                         0, 
163                         0, 
164                         width, 
165                         height,
166                         file->color_model,
167                         BC_YUV420P, 
168                         0,
169                         width,
170                         codec->coded_w);
171                 result = !quicktime_write_data(file, (char*)codec->work_buffer, bytes);
172         }
173
174         quicktime_write_chunk_footer(file, 
175                 trak,
176                 vtrack->current_chunk,
177                 &chunk_atom, 
178                 1);
179
180         vtrack->current_chunk++;
181         return result;
182 }
183
184 void quicktime_init_codec_yv12(quicktime_video_map_t *vtrack)
185 {
186         quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
187
188 /* Init public items */
189         codec_base->priv = calloc(1, sizeof(quicktime_yv12_codec_t));
190         codec_base->delete_vcodec = delete_codec;
191         codec_base->decode_video = decode;
192         codec_base->encode_video = encode;
193         codec_base->decode_audio = 0;
194         codec_base->encode_audio = 0;
195         codec_base->reads_colormodel = reads_colormodel;
196         codec_base->writes_colormodel = writes_colormodel;
197         codec_base->fourcc = QUICKTIME_YUV420;
198         codec_base->title = "YUV 4:2:0 Planar";
199         codec_base->desc = "YUV 4:2:0 Planar";
200 }
201