1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 // Based on LGPL MJPEG/AVI to JPEG/JFIF conversion code from libav
24 // Copyright (c) 2010 Adrian Daerr and Nicolas George
25 // That in turn was adapted from mjpeg2jpeg.c, with original copyright:
26 // Paris 2010 Adrian Daerr, public domain
27 
28 #include "common/memstream.h"
29 #include "common/system.h"
30 #include "common/textconsole.h"
31 #include "graphics/surface.h"
32 #include "image/jpeg.h"
33 
34 #include "image/codecs/mjpeg.h"
35 
36 namespace Common {
37 class SeekableReadStream;
38 }
39 
40 namespace Image {
41 
MJPEGDecoder()42 MJPEGDecoder::MJPEGDecoder() : Codec() {
43 	_pixelFormat = g_system->getScreenFormat();
44 	_surface = 0;
45 }
46 
~MJPEGDecoder()47 MJPEGDecoder::~MJPEGDecoder() {
48 	if (_surface) {
49 		_surface->free();
50 		delete _surface;
51 	}
52 }
53 
54 // Header to be inserted
55 static const byte s_jpegHeader[] = {
56 	0xff, 0xd8,                     // SOI
57 	0xff, 0xe0,                     // APP0
58 	0x00, 0x10,                     // APP0 header size (including
59 	                                // this field, but excluding preceding)
60 	'J', 'F', 'I', 'F', 0x00,       // ID string 'JFIF\0'
61 	0x01, 0x01,                     // version
62 	0x00,                           // bits per type
63 	0x00, 0x00,                     // X density
64 	0x00, 0x00,                     // Y density
65 	0x00,                           // X thumbnail size
66 	0x00
67 };
68 
69 enum {
70 	DHT_SEGMENT_SIZE = 420
71 };
72 
73 static const byte s_dhtSegmentHead[] = { 0xFF, 0xC4, 0x01, 0xA2, 0x00 };
74 static const byte s_dhtSegmentFrag[] = {
75 	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
76 	0x0a, 0x0b, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01,
77 	0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
78 };
79 
80 // Set up the standard Huffman tables (cf. JPEG standard section K.3)
81 // IMPORTANT: these are only valid for 8-bit data precision!
82 static const byte s_mjpegBitsDCLuminance[17] = {
83 	/* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
84 };
85 
86 static const byte s_mjpegValDC[12] = {
87 	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
88 };
89 
90 #if 0
91 static const byte s_mjpegBitsDCChrominance[17] = {
92 	/* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
93 };
94 #endif
95 
96 static const byte s_mjpegBitsACLuminance[17] = {
97 	/* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
98 };
99 
100 static const byte s_mjpegValACLuminance[] = {
101 	0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
102 	0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
103 	0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
104 	0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
105 	0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
106 	0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
107 	0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
108 	0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
109 	0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
110 	0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
111 	0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
112 	0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
113 	0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
114 	0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
115 	0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
116 	0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
117 	0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
118 	0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
119 	0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
120 	0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
121 	0xf9, 0xfa
122 };
123 
124 static const byte s_mjpegBitsACChrominance[17] = {
125 	/* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77
126 };
127 
128 static const byte s_mjpegValACChrominance[] = {
129 	0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
130 	0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
131 	0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
132 	0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
133 	0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
134 	0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
135 	0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
136 	0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
137 	0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
138 	0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
139 	0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
140 	0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
141 	0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
142 	0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
143 	0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
144 	0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
145 	0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
146 	0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
147 	0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
148 	0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
149 	0xf9, 0xfa
150 };
151 
decodeFrame(Common::SeekableReadStream & stream)152 const Graphics::Surface *MJPEGDecoder::decodeFrame(Common::SeekableReadStream &stream) {
153 	// We need to reconstruct an actual JPEG stream here, then feed it to the JPEG decoder
154 	// Yes, this is a pain.
155 
156 	stream.readUint32BE(); // Skip nonsense JPEG header
157 	uint16 inputSkip = stream.readUint16BE() + 4;
158 	uint32 tag = stream.readUint32BE();
159 
160 	if (tag != MKTAG('A', 'V', 'I', '1')) {
161 		warning("Invalid MJPEG tag found");
162 		return 0;
163 	}
164 
165 	uint32 outputSize = stream.size() - inputSkip + sizeof(s_jpegHeader) + DHT_SEGMENT_SIZE;
166 	byte *data = (byte *)malloc(outputSize);
167 
168 	if (!data) {
169 		warning("Failed to allocate data for MJPEG conversion");
170 		return 0;
171 	}
172 
173 	// Copy the header
174 	memcpy(data, s_jpegHeader, sizeof(s_jpegHeader));
175 	uint32 dataOffset = sizeof(s_jpegHeader);
176 
177 	// Write the fake DHT segment
178 	memcpy(data + dataOffset, s_dhtSegmentHead, sizeof(s_dhtSegmentHead));
179 	dataOffset += sizeof(s_dhtSegmentHead);
180 	memcpy(data + dataOffset, s_mjpegBitsDCLuminance + 1, 16);
181 	dataOffset += 16;
182 	memcpy(data + dataOffset, s_dhtSegmentFrag, sizeof(s_dhtSegmentFrag));
183 	dataOffset += sizeof(s_dhtSegmentFrag);
184 	memcpy(data + dataOffset, s_mjpegValDC, 12);
185 	dataOffset += 12;
186 	data[dataOffset++] = 0x10;
187 	memcpy(data + dataOffset, s_mjpegBitsACLuminance + 1, 16);
188 	dataOffset += 16;
189 	memcpy(data + dataOffset, s_mjpegValACLuminance, 162);
190 	dataOffset += 162;
191 	data[dataOffset++] = 0x11;
192 	memcpy(data + dataOffset, s_mjpegBitsACChrominance + 1, 16);
193 	dataOffset += 16;
194 	memcpy(data + dataOffset, s_mjpegValACChrominance, 162);
195 	dataOffset += 162;
196 
197 	// Write the actual data
198 	stream.seek(inputSkip);
199 	stream.read(data + dataOffset, stream.size() - inputSkip);
200 
201 	Common::MemoryReadStream convertedStream(data, outputSize, DisposeAfterUse::YES);
202 	JPEGDecoder jpeg;
203 	jpeg.setOutputPixelFormat(_pixelFormat);
204 
205 	if (!jpeg.loadStream(convertedStream)) {
206 		warning("Failed to decode MJPEG frame");
207 		return 0;
208 	}
209 
210 	if (_surface) {
211 		_surface->free();
212 		delete _surface;
213 	}
214 
215 	_surface = new Graphics::Surface();
216 	_surface->copyFrom(*jpeg.getSurface());
217 
218 	assert(_surface->format == _pixelFormat);
219 
220 	return _surface;
221 }
222 
223 } // End of namespace Image
224