1 /*******************************************************************************
2 rtjpeg_codec.c
3
4 libquicktime - A library for reading and writing quicktime/avi/mp4 files.
5 http://libquicktime.sourceforge.net
6
7 Copyright (C) 2002 Heroine Virtual Ltd.
8 Copyright (C) 2002-2011 Members of the libquicktime project.
9
10 This library is free software; you can redistribute it and/or modify it under
11 the terms of the GNU Lesser General Public License as published by the Free
12 Software Foundation; either version 2.1 of the License, or (at your option)
13 any later version.
14
15 This library is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
18 details.
19
20 You should have received a copy of the GNU Lesser General Public License along
21 with this library; if not, write to the Free Software Foundation, Inc., 51
22 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 *******************************************************************************/
24
25 #include "lqt_private.h"
26 #include "rtjpeg_codec.h"
27 #include <quicktime/colormodels.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #define BLOCK_SIZE 16
32
delete_codec(quicktime_codec_t * codec_base)33 static int delete_codec(quicktime_codec_t *codec_base)
34 {
35 quicktime_rtjpeg_codec_t *codec = codec_base->priv;
36 if(codec->compress_struct)
37 RTjpeg_close(codec->compress_struct);
38 if(codec->rows)
39 lqt_rows_free(codec->rows);
40 if(codec->write_buffer)
41 free(codec->write_buffer);
42
43 if(codec->decompress_struct)
44 RTjpeg_close(codec->decompress_struct);
45 if(codec->read_buffer)
46 free(codec->read_buffer);
47 free(codec);
48 return 0;
49 }
50
decode(quicktime_t * file,unsigned char ** row_pointers,int track)51 static int decode(quicktime_t *file, unsigned char **row_pointers, int track)
52 {
53 int result = 0;
54 int t;
55 int buffer_size;
56 quicktime_video_map_t *vtrack = &file->vtracks[track];
57 // quicktime_trak_t *trak = vtrack->track;
58 quicktime_rtjpeg_codec_t *codec = vtrack->codec->priv;
59
60 if(!row_pointers)
61 {
62 vtrack->stream_cmodel = BC_YUV420P;
63 return 0;
64 }
65
66 if(!codec->decompress_struct) {
67 codec->decompress_struct = RTjpeg_init();
68 if(!codec->decompress_struct)
69 return -1;
70 codec->qt_height = quicktime_video_height(file, track);
71 codec->qt_width = quicktime_video_width(file, track);
72 codec->jpeg_height = BLOCK_SIZE * ((codec->qt_height + BLOCK_SIZE - 1) / (BLOCK_SIZE));
73 codec->jpeg_width = BLOCK_SIZE * ((codec->qt_width + BLOCK_SIZE - 1) / (BLOCK_SIZE));
74 t = RTJ_YUV420;
75 RTjpeg_set_format(codec->decompress_struct, &t);
76
77 codec->rows = lqt_rows_alloc(codec->jpeg_width, codec->jpeg_height,
78 vtrack->stream_cmodel, &codec->rowspan,
79 &codec->rowspan_uv);
80
81 }
82
83 buffer_size = lqt_read_video_frame(file, &codec->read_buffer,
84 &codec->read_buffer_alloc,
85 vtrack->current_position, NULL, track);
86 if(buffer_size <= 0)
87 result = -1;
88
89 if(buffer_size > 0) {
90 if(!result)
91 RTjpeg_decompress(codec->decompress_struct, codec->read_buffer, codec->rows);
92 }
93
94 lqt_rows_copy(row_pointers, codec->rows, codec->qt_width, codec->qt_height,
95 codec->rowspan, codec->rowspan_uv,
96 vtrack->stream_row_span, vtrack->stream_row_span_uv, vtrack->stream_cmodel);
97
98
99 return result;
100 }
101
encode(quicktime_t * file,unsigned char ** row_pointers,int track)102 static int encode(quicktime_t *file, unsigned char **row_pointers, int track)
103 {
104 int result = 0;
105 int i;
106 quicktime_video_map_t *vtrack = &file->vtracks[track];
107 quicktime_trak_t *trak = vtrack->track;
108 quicktime_rtjpeg_codec_t *codec = vtrack->codec->priv;
109
110 if(!row_pointers)
111 {
112 vtrack->stream_cmodel = BC_YUV420P;
113 return 0;
114 }
115
116 if(!codec->compress_struct) {
117 codec->compress_struct = RTjpeg_init();
118 if(!codec->compress_struct)
119 return -1;
120 codec->qt_height = trak->tkhd.track_height;
121 codec->qt_width = trak->tkhd.track_width;
122 codec->jpeg_height = BLOCK_SIZE * ((codec->qt_height + BLOCK_SIZE - 1) / (BLOCK_SIZE));
123 codec->jpeg_width = BLOCK_SIZE * ((codec->qt_width + BLOCK_SIZE - 1) / (BLOCK_SIZE));
124
125 RTjpeg_set_size(codec->compress_struct, &codec->jpeg_width, &codec->jpeg_height);
126 i = codec->Q;
127 i *= 255;
128 i /= 100;
129 RTjpeg_set_quality(codec->compress_struct, &i);
130 i = RTJ_YUV420;
131 RTjpeg_set_format(codec->compress_struct, &i);
132 RTjpeg_set_intra(codec->compress_struct, &codec->K, &codec->LQ, &codec->CQ);
133
134 codec->rows = lqt_rows_alloc(codec->jpeg_width, codec->jpeg_height,
135 vtrack->stream_cmodel, &codec->rowspan,
136 &codec->rowspan_uv);
137
138 codec->write_buffer = malloc(codec->jpeg_width * codec->jpeg_height * 3 / 2 + 100);
139 if(!codec->write_buffer)
140 return -1;
141 }
142
143 lqt_rows_copy(codec->rows, row_pointers, codec->qt_width, codec->qt_height,
144 vtrack->stream_row_span, vtrack->stream_row_span_uv,
145 codec->rowspan, codec->rowspan_uv,
146 vtrack->stream_cmodel);
147
148
149 i = RTjpeg_compress(codec->compress_struct, codec->write_buffer, codec->rows);
150
151 lqt_write_frame_header(file, track,
152 vtrack->current_position,
153 -1, 0);
154
155 result = !quicktime_write_data(file,
156 codec->write_buffer,
157 i);
158 lqt_write_frame_footer(file, track);
159 return result;
160 }
161
set_parameter(quicktime_t * file,int track,const char * key,const void * value)162 static int set_parameter(quicktime_t *file,
163 int track,
164 const char *key,
165 const void *value)
166 {
167 quicktime_rtjpeg_codec_t *codec = file->vtracks[track].codec->priv;
168
169 if(!strcasecmp(key, "rtjpeg_quality"))
170 codec->Q = *(int*)value;
171 if(!strcasecmp(key, "rtjpeg_key_rate"))
172 codec->K = *(int*)value;
173 if(!strcasecmp(key, "rtjpeg_luma_quant"))
174 codec->LQ = *(int*)value;
175 if(!strcasecmp(key, "rtjpeg_chroma_quant"))
176 codec->CQ = *(int*)value;
177 return 0;
178 }
179
quicktime_init_codec_rtjpeg(quicktime_codec_t * codec_base,quicktime_audio_map_t * atrack,quicktime_video_map_t * vtrack)180 void quicktime_init_codec_rtjpeg(quicktime_codec_t * codec_base,
181 quicktime_audio_map_t *atrack,
182 quicktime_video_map_t *vtrack)
183 {
184 quicktime_rtjpeg_codec_t *codec;
185
186 codec = calloc(1, sizeof(*codec));
187 if(!codec)
188 return;
189 codec->Q = 100;
190 codec->K = 25;
191 codec->LQ = 1;
192 codec->CQ = 1;
193
194 codec_base->priv = codec;
195 codec_base->delete_codec = delete_codec;
196 codec_base->decode_video = decode;
197 codec_base->encode_video = encode;
198 codec_base->set_parameter = set_parameter;
199 }
200