allow ffmpeg video to resample curr_pos, add bluray format
[goodguy/history.git] / cinelerra-5.0 / quicktime / yuv4.c
1 #include "colormodels.h"
2 #include "funcprotos.h"
3 #include "quicktime.h"
4 #include "yuv4.h"
5
6 typedef struct
7 {
8         unsigned char *work_buffer;
9         int coded_w, coded_h;
10
11         int bytes_per_line;
12         int initialized;
13
14         uint8_t ** rows;
15   } quicktime_yuv4_codec_t;
16
17 static void quicktime_delete_codec_yuv4(quicktime_video_map_t *vtrack)
18 {
19         quicktime_yuv4_codec_t *codec;
20
21         codec = ((quicktime_codec_t*)vtrack->codec)->priv;
22         if(codec->work_buffer) free(codec->work_buffer);
23         if(codec->rows) free(codec->rows);
24         free(codec);
25 }
26
27 static void convert_encode_yuv4(quicktime_yuv4_codec_t *codec)
28 {
29         int y, x;
30         unsigned char *outp = codec->work_buffer;
31         for(y = 0; y < codec->coded_h; y+=2) {
32                 int y1 = y+1 >= codec->coded_h ? y : y+1;
33                 unsigned char *row0 = codec->work_buffer + y * codec->bytes_per_line;
34                 unsigned char *row1 = codec->work_buffer + y1 * codec->bytes_per_line;
35                 for(x = 0; x < codec->bytes_per_line; x+=2) {
36                         int y00 = *row0++, u  = *row0++, v  = *row0++;
37                         int y01 = *row0++; u += *row0++, v += *row0++;
38                         int y10 = *row1++; u += *row1++, v += *row1++;
39                         int y11 = *row1++; u += *row1++, v += *row1++;
40                         *outp++ = u/4;  *outp++ = v/4;
41                         *outp++ = y00;  *outp++ = y01;
42                         *outp++ = y10;  *outp++ = y11;
43                 }
44         }
45 }
46
47 static void convert_decode_yuv4(quicktime_yuv4_codec_t *codec)
48 {
49         int y, x;
50         unsigned char *inp = codec->work_buffer;
51         for(y = 0; y < codec->coded_h; y+=2) {
52                 int y1 = y+1 >= codec->coded_h ? y : y+1;
53                 unsigned char *row0 = codec->work_buffer + y * codec->bytes_per_line;
54                 unsigned char *row1 = codec->work_buffer + y1 * codec->bytes_per_line;
55                 for(x = 0; x < codec->bytes_per_line; ) {
56                         int   u = *inp++,    v = *inp++;
57                         int y00 = *inp++,  y01 = *inp++;
58                         int y10 = *inp++,  y11 = *inp++;
59                         *row0++ = y00;  *row0++ = u;  *row0++ = v;
60                         *row0++ = y01;  *row0++ = u;  *row0++ = v;
61                         *row1++ = y10;  *row1++ = u;  *row1++ = v;
62                         *row1++ = y11;  *row1++ = u;  *row1++ = v;
63                 }
64         }
65 }
66
67
68 static void initialize(quicktime_video_map_t *vtrack, quicktime_yuv4_codec_t *codec,
69                        int width, int height)
70 {
71         if(!codec->initialized)
72         {
73                 int y;
74 /* Init private items */
75                 codec->coded_w = (int)((float)width / 4 + 0.5) * 4;
76 //              codec->coded_h = (int)((float)vtrack->track->tkhd.track_height / 4 + 0.5) * 4;
77                 codec->coded_h = height;
78                 codec->bytes_per_line = codec->coded_w * 2;
79                 codec->work_buffer = malloc(codec->bytes_per_line * codec->coded_h);
80                 codec->rows = malloc(height * sizeof(*(codec->rows)));
81                 for(y = 0; y < height; y++)
82                         codec->rows[y] = &codec->work_buffer[y * codec->bytes_per_line];
83                 codec->initialized = 1;
84     }
85 }
86
87 static int decode(quicktime_t *file, unsigned char **row_pointers, int track)
88 {
89         int bytes;
90         quicktime_video_map_t *vtrack = &(file->vtracks[track]);
91         quicktime_yuv4_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
92         int width = quicktime_video_width(file, track);
93         int height = quicktime_video_height(file, track);
94         int result = 0;
95
96         initialize(vtrack, codec, width, height);
97         quicktime_set_video_position(file, vtrack->current_position, track);
98         bytes = quicktime_frame_size(file, vtrack->current_position, track);
99
100         result = !quicktime_read_data(file, (char*)codec->work_buffer, bytes);
101         convert_decode_yuv4(codec);
102
103         cmodel_transfer(row_pointers, codec->rows,
104                 row_pointers[0], row_pointers[1], row_pointers[2],
105                 0, 0, 0,
106                 file->in_x, file->in_y, file->in_w, file->in_h,
107                 0, 0, file->out_w, file->out_h,
108                 BC_YUV888, file->color_model,
109                 0, codec->coded_w, file->out_w);
110
111         return result;
112 }
113
114 static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
115 {
116         int bytes;
117         quicktime_video_map_t *vtrack = &(file->vtracks[track]);
118         quicktime_trak_t *trak = vtrack->track;
119         quicktime_yuv4_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv;
120         int result = 1;
121         int width = vtrack->track->tkhd.track_width;
122         int height = vtrack->track->tkhd.track_height;
123         quicktime_atom_t chunk_atom;
124         initialize(vtrack, codec, width, height);
125         bytes = height * codec->bytes_per_line;
126
127         cmodel_transfer(codec->rows, row_pointers,
128                 0, 0, 0,
129                 row_pointers[0], row_pointers[1], row_pointers[2],
130                 0, 0, width, height,
131                 0, 0, width, height,
132                 file->color_model, BC_YUV888,
133                 0, width, codec->coded_w);
134
135         convert_encode_yuv4(codec);
136
137         quicktime_write_chunk_header(file, trak, &chunk_atom);
138         result = !quicktime_write_data(file, (char*)codec->work_buffer, bytes);
139         quicktime_write_chunk_footer(file, trak,
140                 vtrack->current_chunk, &chunk_atom, 1);
141
142         vtrack->current_chunk++;
143         return result;
144 }
145
146 static int reads_colormodel(quicktime_t *file,
147                 int colormodel,
148                 int track)
149 {
150
151         return (colormodel == BC_RGB888 ||
152                 colormodel == BC_YUV888 ||
153                 colormodel == BC_YUV422P ||
154                 colormodel == BC_YUV422);
155 }
156
157 static int writes_colormodel(quicktime_t *file,
158                 int colormodel,
159                 int track)
160 {
161
162         return (colormodel == BC_RGB888 ||
163                 colormodel == BC_YUV888 ||
164                 colormodel == BC_YUV422P ||
165                 colormodel == BC_YUV422);
166 }
167
168
169 void quicktime_init_codec_yuv4(quicktime_video_map_t *vtrack)
170 {
171         quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec;
172
173 /* Init public items */
174         codec_base->priv = calloc(1, sizeof(quicktime_yuv4_codec_t));
175         codec_base->delete_vcodec = quicktime_delete_codec_yuv4;
176         codec_base->decode_video = decode;
177         codec_base->encode_video = encode;
178         codec_base->decode_audio = 0;
179         codec_base->encode_audio = 0;
180         codec_base->reads_colormodel = reads_colormodel;
181         codec_base->writes_colormodel = writes_colormodel;
182         codec_base->fourcc = QUICKTIME_YUV4;
183         codec_base->title = "YUV 4:2:0 packed";
184         codec_base->desc = "YUV 4:2:0 packed (Not standardized)";
185 }
186
187