aboutsummaryrefslogtreecommitdiff
path: root/Src/jpeg
diff options
context:
space:
mode:
Diffstat (limited to 'Src/jpeg')
-rw-r--r--Src/jpeg/amg.cpp121
-rw-r--r--Src/jpeg/amg.h39
-rw-r--r--Src/jpeg/api__jpeg.h12
-rw-r--r--Src/jpeg/avi_mjpg_decoder.cpp270
-rw-r--r--Src/jpeg/avi_mjpg_decoder.h50
-rw-r--r--Src/jpeg/jpeg.rc76
-rw-r--r--Src/jpeg/jpeg.sln43
-rw-r--r--Src/jpeg/jpeg.vcxproj268
-rw-r--r--Src/jpeg/jpeg.vcxproj.filters74
-rw-r--r--Src/jpeg/loader_jpg.cpp223
-rw-r--r--Src/jpeg/loader_jpg.h23
-rw-r--r--Src/jpeg/main.h6
-rw-r--r--Src/jpeg/mp4_jpeg_decoder.cpp91
-rw-r--r--Src/jpeg/mp4_jpeg_decoder.h29
-rw-r--r--Src/jpeg/resource.h14
-rw-r--r--Src/jpeg/version.rc239
-rw-r--r--Src/jpeg/w5s.cpp96
-rw-r--r--Src/jpeg/w5s.h15
-rw-r--r--Src/jpeg/writer_jpg.cpp138
-rw-r--r--Src/jpeg/writer_jpg.h25
20 files changed, 1652 insertions, 0 deletions
diff --git a/Src/jpeg/amg.cpp b/Src/jpeg/amg.cpp
new file mode 100644
index 00000000..cca284ca
--- /dev/null
+++ b/Src/jpeg/amg.cpp
@@ -0,0 +1,121 @@
+#include "amg.h"
+#include "api__jpeg.h"
+#include <setjmp.h>
+extern "C"
+{
+#undef FAR
+#include "jpeglib.h"
+// our reader...
+
+ static void init_source( j_decompress_ptr cinfo )
+ {}
+ static const JOCTET jpeg_eof[] = { (JOCTET)0xFF, (JOCTET)JPEG_EOI };
+ static boolean fill_input_buffer( j_decompress_ptr cinfo )
+ {
+ cinfo->src->next_input_byte = jpeg_eof;
+ cinfo->src->bytes_in_buffer = 2;
+ return TRUE;
+ }
+ static void skip_input_data( j_decompress_ptr cinfo, long num_bytes )
+ {
+ //my_src_ptr src = (my_src_ptr) cinfo->src;
+ if ( num_bytes > 0 )
+ {
+ if ( num_bytes > (long)cinfo->src->bytes_in_buffer )
+ {
+ fill_input_buffer( cinfo );
+ }
+ else
+ {
+ cinfo->src->next_input_byte += (size_t)num_bytes;
+ cinfo->src->bytes_in_buffer -= (size_t)num_bytes;
+ }
+ }
+ }
+ static void term_source( j_decompress_ptr cinfo )
+ {}
+
+
+ typedef struct
+ {
+ jpeg_destination_mgr pub;
+ uint8_t *buf;
+ int len;
+ } my_destination_mgr;
+
+ void init_destination( j_compress_ptr cinfo );
+ boolean empty_output_buffer( j_compress_ptr cinfo );
+ void term_destination( j_compress_ptr cinfo );
+ static void wasabi_jpgload_error_exit( j_common_ptr cinfo )
+ {
+ jmp_buf *stack_env = (jmp_buf *)cinfo->client_data;
+ longjmp( *stack_env, 1 );
+ }
+};
+
+
+
+int AMGSucks::WriteAlbumArt(const void *data, size_t data_len, void **out, int *out_len)
+{
+ *out = 0;
+ jmp_buf stack_env;
+
+ jpeg_decompress_struct cinfo_dec={0};
+ jpeg_compress_struct cinfo={0};
+ cinfo.client_data=&stack_env;
+ cinfo_dec.client_data=&stack_env;
+
+ if (setjmp(stack_env))
+ {
+ // longjmp will goto here
+ jpeg_destroy_decompress(&cinfo_dec);
+ jpeg_destroy_compress(&cinfo);
+ return 1;
+ }
+
+ jpeg_error_mgr jerr;
+ jpeg_source_mgr src = {(const JOCTET *)data,data_len,init_source,fill_input_buffer,skip_input_data,jpeg_resync_to_restart,term_source};
+ cinfo_dec.err = jpeg_std_error(&jerr);
+ jpeg_create_decompress(&cinfo_dec);
+ cinfo_dec.err->error_exit = wasabi_jpgload_error_exit;
+ cinfo_dec.src = &src;
+
+ if (jpeg_read_header(&cinfo_dec, TRUE) == JPEG_HEADER_OK)
+ {
+ cinfo.err = cinfo_dec.err;
+ jpeg_create_compress(&cinfo);
+ cinfo.err->error_exit = wasabi_jpgload_error_exit;
+
+ my_destination_mgr dest = {{0,65536,init_destination,empty_output_buffer,term_destination},0,65536};
+ dest.buf = (uint8_t *)WASABI_API_MEMMGR->sysMalloc(65536);
+ dest.pub.next_output_byte = dest.buf;
+ cinfo.dest = (jpeg_destination_mgr*)&dest;
+ cinfo.image_width = cinfo_dec.image_width;
+ cinfo.image_height = cinfo_dec.image_height;
+ cinfo.input_components = 4;
+ cinfo.in_color_space = JCS_RGB;
+
+ jpeg_copy_critical_parameters(&cinfo_dec, &cinfo);
+ jvirt_barray_ptr *stuff = jpeg_read_coefficients(&cinfo_dec);
+ jpeg_write_coefficients(&cinfo, stuff);
+ const char *blah = "AMG/AOL";
+ jpeg_write_marker(&cinfo, JPEG_COM, (JOCTET *)blah, (unsigned int)strlen(blah));
+
+ jpeg_finish_compress(&cinfo);
+
+ *out = dest.buf;
+ *out_len = dest.len - (int)dest.pub.free_in_buffer;
+
+ jpeg_destroy_decompress(&cinfo_dec);
+ jpeg_destroy_compress(&cinfo);
+
+ return 0;
+ }
+ return 1;
+}
+
+#define CBCLASS AMGSucks
+START_DISPATCH;
+CB(WRITEALBUMART, WriteAlbumArt);
+END_DISPATCH;
+#undef CBCLASS \ No newline at end of file
diff --git a/Src/jpeg/amg.h b/Src/jpeg/amg.h
new file mode 100644
index 00000000..f332cc55
--- /dev/null
+++ b/Src/jpeg/amg.h
@@ -0,0 +1,39 @@
+#pragma once
+
+#include <bfc/dispatch.h>
+#include <api/service/services.h>
+class api_amgsucks : public Dispatchable
+{
+protected:
+ api_amgsucks() {}
+ ~api_amgsucks() {}
+public:
+ int WriteAlbumArt(const void *data, size_t data_len, void **out, int *out_len);
+
+ DISPATCH_CODES
+ {
+ WRITEALBUMART = 0,
+ };
+};
+
+inline int api_amgsucks::WriteAlbumArt(const void *data, size_t data_len, void **out, int *out_len)
+{
+ return _call(WRITEALBUMART, (int)2, data, data_len, out, out_len);
+}
+
+// {E93907C8-8CFD-47dc-87FC-80B5B03716CB}
+static const GUID amgSucksGUID =
+{ 0xe93907c8, 0x8cfd, 0x47dc, { 0x87, 0xfc, 0x80, 0xb5, 0xb0, 0x37, 0x16, 0xcb } };
+
+
+class AMGSucks : public api_amgsucks
+{
+public:
+ static FOURCC getServiceType() { return WaSvc::UNIQUE; }
+ static const char *getServiceName() { return "AMG Sucks"; }
+ static GUID getServiceGuid() { return amgSucksGUID; }
+private:
+ int WriteAlbumArt(const void *data, size_t data_len, void **out, int *out_len);
+protected:
+ RECVS_DISPATCH;
+}; \ No newline at end of file
diff --git a/Src/jpeg/api__jpeg.h b/Src/jpeg/api__jpeg.h
new file mode 100644
index 00000000..76b8a904
--- /dev/null
+++ b/Src/jpeg/api__jpeg.h
@@ -0,0 +1,12 @@
+#ifndef NULLSOFT_APIH
+#define NULLSOFT_APIH
+#include <api/service/api_service.h>
+
+extern api_service *serviceManager;
+#define WASABI_API_SVC serviceManager
+
+#include <api/memmgr/api_memmgr.h>
+extern api_memmgr *memoryManager;
+#define WASABI_API_MEMMGR memoryManager
+
+#endif \ No newline at end of file
diff --git a/Src/jpeg/avi_mjpg_decoder.cpp b/Src/jpeg/avi_mjpg_decoder.cpp
new file mode 100644
index 00000000..21e0401b
--- /dev/null
+++ b/Src/jpeg/avi_mjpg_decoder.cpp
@@ -0,0 +1,270 @@
+#include "api__jpeg.h"
+#include "avi_mjpg_decoder.h"
+#include "../Winamp/wa_ipc.h"
+#include <limits.h>
+#include <intsafe.h>
+
+#include <setjmp.h>
+
+extern "C"
+{
+#undef FAR
+#include "jpeglib.h"
+};
+
+
+uint8_t mjpeg_header[0x1A4] =
+{
+ /* JPEG DHT Segment for YCrCb omitted from MJPG data */
+ 0xFF,0xC4,0x01,0xA2,
+ 0x00,0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x01,0x00,0x03,0x01,0x01,0x01,0x01,
+ 0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x08,0x09,0x0A,0x0B,0x10,0x00,0x02,0x01,0x03,0x03,0x02,0x04,0x03,0x05,0x05,0x04,0x04,0x00,
+ 0x00,0x01,0x7D,0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,
+ 0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xA1,0x08,0x23,0x42,0xB1,0xC1,0x15,0x52,0xD1,0xF0,0x24,
+ 0x33,0x62,0x72,0x82,0x09,0x0A,0x16,0x17,0x18,0x19,0x1A,0x25,0x26,0x27,0x28,0x29,0x2A,0x34,
+ 0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x53,0x54,0x55,0x56,
+ 0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78,
+ 0x79,0x7A,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,
+ 0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,
+ 0xBA,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,
+ 0xDA,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,
+ 0xF8,0xF9,0xFA,0x11,0x00,0x02,0x01,0x02,0x04,0x04,0x03,0x04,0x07,0x05,0x04,0x04,0x00,0x01,
+ 0x02,0x77,0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,
+ 0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xA1,0xB1,0xC1,0x09,0x23,0x33,0x52,0xF0,0x15,0x62,
+ 0x72,0xD1,0x0A,0x16,0x24,0x34,0xE1,0x25,0xF1,0x17,0x18,0x19,0x1A,0x26,0x27,0x28,0x29,0x2A,
+ 0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x53,0x54,0x55,0x56,
+ 0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x73,0x74,0x75,0x76,0x77,0x78,
+ 0x79,0x7A,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,
+ 0x99,0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,
+ 0xB9,0xBA,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,
+ 0xD9,0xDA,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,
+ 0xF9,0xFA
+};
+
+int AVIDecoderCreator::CreateVideoDecoder( const nsavi::AVIH *avi_header, const nsavi::STRH *stream_header, const nsavi::STRF *stream_format, const nsavi::STRD *stream_data, ifc_avivideodecoder **decoder )
+{
+ nsavi::video_format *format = (nsavi::video_format *)stream_format;
+ if ( format )
+ {
+ if ( format->compression == 'GPJM' ) // mjpg
+ {
+ *decoder = AVIMJPEG::CreateDecoder( format );
+ if ( *decoder )
+ return CREATEDECODER_SUCCESS;
+ else
+ return CREATEDECODER_FAILURE;
+ }
+ }
+
+ return CREATEDECODER_NOT_MINE;
+}
+
+
+#define CBCLASS AVIDecoderCreator
+START_DISPATCH;
+CB( CREATE_VIDEO_DECODER, CreateVideoDecoder )
+END_DISPATCH;
+#undef CBCLASS
+
+AVIMJPEG *AVIMJPEG::CreateDecoder( nsavi::video_format *stream_format )
+{
+ AVIMJPEG *decoder = new AVIMJPEG( stream_format );
+ if ( !decoder )
+ {
+ return 0;
+ }
+
+ return decoder;
+}
+
+
+AVIMJPEG::AVIMJPEG( nsavi::video_format *stream_format ) : stream_format( stream_format )
+{
+
+ cinfo.err = jpeg_std_error( &jerr );
+
+ jpeg_create_decompress( &cinfo );
+
+ jpegLoader = 0;
+ width = 0;
+ height = 0;
+ decoded_image = 0;
+ image_size = 0;
+ image_outputted = true;
+}
+
+
+
+int AVIMJPEG::GetOutputProperties( int *x, int *y, int *color_format, double *aspect_ratio, int *flip )
+{
+ *x = stream_format->width;
+ *y = stream_format->height;
+ *color_format = '23GR'; // RGB32
+ *aspect_ratio = 1.0;
+ *flip = 0;
+
+ return AVI_SUCCESS;
+}
+
+struct mjpeg_source_mgr
+{
+ jpeg_source_mgr src;
+ int state;
+ const JOCTET *input_buffer;
+ size_t input_buffer_bytes;
+
+};
+
+static void init_source( j_decompress_ptr cinfo )
+{}
+
+static const JOCTET jpeg_eof[] = {(JOCTET) 0xFF, (JOCTET) JPEG_EOI};
+
+static boolean fill_input_buffer( j_decompress_ptr cinfo )
+{
+ mjpeg_source_mgr *msrc = (mjpeg_source_mgr *)cinfo->src;
+ jpeg_source_mgr *src = &msrc->src;
+
+
+ switch ( msrc->state++ )
+ {
+ case 0:
+ src->next_input_byte = mjpeg_header;
+ src->bytes_in_buffer = sizeof( mjpeg_header );
+ return TRUE;
+ case 1:
+ src->next_input_byte = msrc->input_buffer + 2;
+ src->bytes_in_buffer = msrc->input_buffer_bytes - 2;
+ return TRUE;
+ case 2:
+ src->next_input_byte = jpeg_eof;
+ src->bytes_in_buffer = 2;
+ return TRUE;
+ }
+
+ return TRUE;
+}
+
+void skip_input_data( j_decompress_ptr cinfo, long num_bytes )
+{
+ if ( num_bytes > 0 )
+ {
+ if ( num_bytes > (long)cinfo->src->bytes_in_buffer )
+ {
+ fill_input_buffer( cinfo );
+ }
+ else
+ {
+ cinfo->src->next_input_byte += (size_t)num_bytes;
+ cinfo->src->bytes_in_buffer -= (size_t)num_bytes;
+ }
+ }
+}
+
+void term_source( j_decompress_ptr cinfo )
+{}
+
+
+static void wasabi_jpgload_error_exit( j_common_ptr cinfo )
+{
+ jmp_buf *stack_env = (jmp_buf *)cinfo->client_data;
+ longjmp( *stack_env, 1 );
+}
+
+int AVIMJPEG::DecodeChunk( uint16_t type, const void *inputBuffer, size_t inputBufferBytes )
+{
+ mjpeg_source_mgr src = { {(const JOCTET *)inputBuffer,2,init_source,fill_input_buffer,skip_input_data,jpeg_resync_to_restart,term_source}, 0, (const JOCTET *)inputBuffer, inputBufferBytes };
+
+ cinfo.src = &src.src;
+
+ /* set up error handling. basically C style exceptions :) */
+ jmp_buf stack_env;
+ cinfo.client_data = &stack_env;
+ cinfo.err->error_exit = wasabi_jpgload_error_exit;
+ if ( setjmp( stack_env ) )
+ {
+ // longjmp will goto here
+ jpeg_destroy_decompress( &cinfo );
+ return AVI_FAILURE;
+ }
+
+ if ( jpeg_read_header( &cinfo, TRUE ) == JPEG_HEADER_OK )
+ {
+ cinfo.out_color_space = JCS_RGB;
+
+ jpeg_start_decompress( &cinfo );
+
+ int this_image_size = cinfo.output_width * cinfo.output_height * 4;
+ if ( this_image_size > image_size )
+ {
+ image_size = this_image_size;
+ decoded_image = malloc( image_size );
+ }
+ ARGB32 *p = (ARGB32 *)decoded_image;// + (cinfo.output_width * cinfo.output_height);
+
+ while ( cinfo.output_scanline < cinfo.output_height )
+ {
+ //p -= cinfo.output_width;
+ jpeg_read_scanlines( &cinfo, (JSAMPARRAY)&p, 1 );
+
+ // this is pretty homo, but it has to be done
+ for ( unsigned int i = 0; i < cinfo.output_width; i++ )
+ // full alpha shift red to correct place leave green alone shift blue to correct place
+ p[ i ] = ( 0xff000000 | ( ( p[ i ] & 0x0000ff ) << 16 ) | ( p[ i ] & 0x00ff00 ) | ( ( p[ i ] & 0xff0000 ) >> 16 ) );
+
+ p += cinfo.output_width;
+ }
+
+ //if (w) *w = cinfo.output_width;
+ //if (h) *h = cinfo.output_height;
+ jpeg_finish_decompress( &cinfo );
+
+ }
+ //jpeg_destroy_decompress(&cinfo);
+
+ image_outputted = false;
+
+ return AVI_SUCCESS;
+}
+
+void AVIMJPEG::Flush()
+{
+
+}
+
+int AVIMJPEG::GetPicture( void **data, void **decoder_data )
+{
+ if ( image_outputted )
+ return AVI_FAILURE;
+
+ *data = decoded_image;
+ *decoder_data = 0;
+ image_outputted = true;
+
+ return AVI_SUCCESS;
+}
+
+void AVIMJPEG::FreePicture( void *data, void *decoder_data )
+{
+
+}
+
+void AVIMJPEG::Close()
+{
+ delete jpegLoader;
+ delete this;
+}
+
+
+#define CBCLASS AVIMJPEG
+START_DISPATCH;
+CB( GET_OUTPUT_PROPERTIES, GetOutputProperties )
+CB( DECODE_CHUNK, DecodeChunk )
+VCB( FLUSH, Flush )
+VCB( CLOSE, Close )
+CB( GET_PICTURE, GetPicture )
+VCB( FREE_PICTURE, FreePicture )
+END_DISPATCH;
+#undef CBCLASS
diff --git a/Src/jpeg/avi_mjpg_decoder.h b/Src/jpeg/avi_mjpg_decoder.h
new file mode 100644
index 00000000..01ba80d1
--- /dev/null
+++ b/Src/jpeg/avi_mjpg_decoder.h
@@ -0,0 +1,50 @@
+#pragma once
+#include "../Plugins/Input/in_avi/ifc_avivideodecoder.h"
+#include "../Plugins/Input/in_avi/svc_avidecoder.h"
+#include "../nsavi/avi_header.h"
+#include "loader_jpg.h"
+extern "C"
+{
+#undef FAR
+#include "jpeglib.h"
+};
+
+// {F54E12B2-1B6B-48ac-B65D-F33B690A4F81}
+static const GUID avi_jpeg_guid =
+{ 0xf54e12b2, 0x1b6b, 0x48ac, { 0xb6, 0x5d, 0xf3, 0x3b, 0x69, 0xa, 0x4f, 0x81 } };
+
+
+class AVIDecoderCreator : public svc_avidecoder
+{
+public:
+ static const char *getServiceName() { return "JPEG AVI Decoder"; }
+ static GUID getServiceGuid() { return avi_jpeg_guid; }
+ int CreateVideoDecoder(const nsavi::AVIH *avi_header, const nsavi::STRH *stream_header, const nsavi::STRF *stream_format, const nsavi::STRD *stream_data, ifc_avivideodecoder **decoder);
+protected:
+ RECVS_DISPATCH;
+};
+
+class AVIMJPEG : public ifc_avivideodecoder
+{
+public:
+ AVIMJPEG(nsavi::video_format *stream_format);
+ static AVIMJPEG *CreateDecoder(nsavi::video_format *stream_format);
+ int GetOutputProperties(int *x, int *y, int *color_format, double *aspect_ratio, int *flip);
+ int DecodeChunk(uint16_t type, const void *inputBuffer, size_t inputBufferBytes);
+ void Flush();
+ void Close();
+ int GetPicture(void **data, void **decoder_data);
+ void FreePicture(void *data, void *decoder_data);
+
+private:
+ nsavi::video_format *stream_format;
+ JpgLoad *jpegLoader;
+ int width, height;
+ int image_size;
+ void *decoded_image; // UYVY
+ bool image_outputted;
+ jpeg_decompress_struct cinfo;
+ jpeg_error_mgr jerr;
+protected:
+ RECVS_DISPATCH;
+}; \ No newline at end of file
diff --git a/Src/jpeg/jpeg.rc b/Src/jpeg/jpeg.rc
new file mode 100644
index 00000000..fcff7711
--- /dev/null
+++ b/Src/jpeg/jpeg.rc
@@ -0,0 +1,76 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.K.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "#include ""version.rc2""\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.K.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#include "version.rc2"
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/Src/jpeg/jpeg.sln b/Src/jpeg/jpeg.sln
new file mode 100644
index 00000000..de59daab
--- /dev/null
+++ b/Src/jpeg/jpeg.sln
@@ -0,0 +1,43 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29424.173
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jpeg", "jpeg.vcxproj", "{74EADF6F-F023-4D8C-B03A-5258B192A5E2}"
+ ProjectSection(ProjectDependencies) = postProject
+ {4F4B5925-2D0B-48DB-BBB0-D321B14EF621} = {4F4B5925-2D0B-48DB-BBB0-D321B14EF621}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ijg", "..\ijg\ijg.vcxproj", "{4F4B5925-2D0B-48DB-BBB0-D321B14EF621}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {74EADF6F-F023-4D8C-B03A-5258B192A5E2}.Debug|Win32.ActiveCfg = Debug|Win32
+ {74EADF6F-F023-4D8C-B03A-5258B192A5E2}.Debug|Win32.Build.0 = Debug|Win32
+ {74EADF6F-F023-4D8C-B03A-5258B192A5E2}.Debug|x64.ActiveCfg = Debug|x64
+ {74EADF6F-F023-4D8C-B03A-5258B192A5E2}.Debug|x64.Build.0 = Debug|x64
+ {74EADF6F-F023-4D8C-B03A-5258B192A5E2}.Release|Win32.ActiveCfg = Release|Win32
+ {74EADF6F-F023-4D8C-B03A-5258B192A5E2}.Release|Win32.Build.0 = Release|Win32
+ {74EADF6F-F023-4D8C-B03A-5258B192A5E2}.Release|x64.ActiveCfg = Release|x64
+ {74EADF6F-F023-4D8C-B03A-5258B192A5E2}.Release|x64.Build.0 = Release|x64
+ {4F4B5925-2D0B-48DB-BBB0-D321B14EF621}.Debug|Win32.ActiveCfg = Debug|Win32
+ {4F4B5925-2D0B-48DB-BBB0-D321B14EF621}.Debug|Win32.Build.0 = Debug|Win32
+ {4F4B5925-2D0B-48DB-BBB0-D321B14EF621}.Debug|x64.ActiveCfg = Debug|x64
+ {4F4B5925-2D0B-48DB-BBB0-D321B14EF621}.Debug|x64.Build.0 = Debug|x64
+ {4F4B5925-2D0B-48DB-BBB0-D321B14EF621}.Release|Win32.ActiveCfg = Release|Win32
+ {4F4B5925-2D0B-48DB-BBB0-D321B14EF621}.Release|Win32.Build.0 = Release|Win32
+ {4F4B5925-2D0B-48DB-BBB0-D321B14EF621}.Release|x64.ActiveCfg = Release|x64
+ {4F4B5925-2D0B-48DB-BBB0-D321B14EF621}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {1D358370-7495-448D-BD0B-186B11C8D08E}
+ EndGlobalSection
+EndGlobal
diff --git a/Src/jpeg/jpeg.vcxproj b/Src/jpeg/jpeg.vcxproj
new file mode 100644
index 00000000..bd373cc7
--- /dev/null
+++ b/Src/jpeg/jpeg.vcxproj
@@ -0,0 +1,268 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{74EADF6F-F023-4D8C-B03A-5258B192A5E2}</ProjectGuid>
+ <RootNamespace>jpeg</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
+ <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
+ <TargetExt>.w5s</TargetExt>
+ <IncludePath>$(IncludePath)</IncludePath>
+ <LibraryPath>$(LibraryPath)</LibraryPath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
+ <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
+ <TargetExt>.w5s</TargetExt>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
+ <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
+ <TargetExt>.w5s</TargetExt>
+ <IncludePath>$(IncludePath)</IncludePath>
+ <LibraryPath>$(LibraryPath)</LibraryPath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
+ <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
+ <TargetExt>.w5s</TargetExt>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <VcpkgConfiguration>Debug</VcpkgConfiguration>
+ <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
+ <VcpkgConfiguration>Debug</VcpkgConfiguration>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>.;../Wasabi;../libmp4v2;../libmp4v2/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;JPEG_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>false</MinimalRebuild>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(ProjectName).w5s</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(ProjectDir)x86_Debug\$(ProjectName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ <PostBuildEvent>
+ <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\
+xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\ </Command>
+ <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\'</Message>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>.;../Wasabi;../libmp4v2;../libmp4v2/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;JPEG_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>false</MinimalRebuild>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(ProjectName).w5s</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(ProjectDir)x64_Debug\$(ProjectName).lib</ImportLibrary>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ <PostBuildEvent>
+ <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\
+xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\ </Command>
+ <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\'</Message>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>.;../Wasabi;../libmp4v2;../libmp4v2/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;JPEG_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>None</DebugInformationFormat>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(ProjectName).w5s</OutputFile>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(ProjectDir)x86_Release\$(ProjectName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ <PostBuildEvent>
+ <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\ </Command>
+ <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\'</Message>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>.;../Wasabi;../libmp4v2;../libmp4v2/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;JPEG_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>None</DebugInformationFormat>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(ProjectName).w5s</OutputFile>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(ProjectDir)x64_Release\$(ProjectName).lib</ImportLibrary>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ </Link>
+ <PostBuildEvent>
+ <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\ </Command>
+ <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\System\'</Message>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\external_dependencies\libmp4v2\libmp4v2.vcxproj">
+ <Project>{efb9b882-6a8b-463d-a8e3-a2807afc5d9f}</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\Wasabi\Wasabi.vcxproj">
+ <Project>{3e0bfa8a-b86a-42e9-a33f-ec294f823f7f}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="amg.cpp" />
+ <ClCompile Include="avi_mjpg_decoder.cpp" />
+ <ClCompile Include="loader_jpg.cpp" />
+ <ClCompile Include="mp4_jpeg_decoder.cpp" />
+ <ClCompile Include="w5s.cpp" />
+ <ClCompile Include="writer_jpg.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\Wasabi\api\service\svcs\svc_imgload.h" />
+ <ClInclude Include="..\Wasabi\api\service\svcs\svc_imgwrite.h" />
+ <ClInclude Include="amg.h" />
+ <ClInclude Include="api__jpeg.h" />
+ <ClInclude Include="avi_mjpg_decoder.h" />
+ <ClInclude Include="loader_jpg.h" />
+ <ClInclude Include="main.h" />
+ <ClInclude Include="mp4_jpeg_decoder.h" />
+ <ClInclude Include="resource.h" />
+ <ClInclude Include="w5s.h" />
+ <ClInclude Include="writer_jpg.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="jpeg.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Src/jpeg/jpeg.vcxproj.filters b/Src/jpeg/jpeg.vcxproj.filters
new file mode 100644
index 00000000..41384744
--- /dev/null
+++ b/Src/jpeg/jpeg.vcxproj.filters
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="amg.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="avi_mjpg_decoder.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="loader_jpg.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="mp4_jpeg_decoder.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="w5s.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="writer_jpg.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="amg.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="api__jpeg.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="avi_mjpg_decoder.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="loader_jpg.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="main.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="mp4_jpeg_decoder.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\Wasabi\api\service\svcs\svc_imgload.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\Wasabi\api\service\svcs\svc_imgwrite.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="w5s.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="writer_jpg.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{c34a3258-e5bd-4d12-9c43-db9aff734101}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{a0ca09db-4077-4800-9f71-92c88a75bc27}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Ressource Files">
+ <UniqueIdentifier>{fbabf673-97e4-4a24-b3b5-4c0848ca40b3}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="jpeg.rc">
+ <Filter>Ressource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Src/jpeg/loader_jpg.cpp b/Src/jpeg/loader_jpg.cpp
new file mode 100644
index 00000000..234ca4d5
--- /dev/null
+++ b/Src/jpeg/loader_jpg.cpp
@@ -0,0 +1,223 @@
+#include "main.h"
+
+#include "loader_jpg.h"
+
+#include "api__jpeg.h"
+#include "../xml/ifc_xmlreaderparams.h"
+#include <api/memmgr/api_memmgr.h>
+#include <shlwapi.h>
+#include <setjmp.h>
+
+#include <wingdi.h>
+#include <intsafe.h>
+
+/*BIG BIG THING TO NOTE
+I have modified jmorecfg.h line 319 to specify 4 bytes per pixel with RGB. it is normally three.
+*/
+extern "C"
+{
+#undef FAR
+#include "jpeglib.h"
+};
+
+int JpgLoad::isMine( const wchar_t *filename )
+{
+ if ( !filename )
+ return 0;
+
+ const wchar_t *ext = PathFindExtensionW( filename );
+
+ if ( !ext )
+ return 0;
+
+ if ( !_wcsicmp( ext, L".jpg" ) )
+ return 1;
+
+ if ( !_wcsicmp( ext, L".jpeg" ) )
+ return 1;
+
+ return 0;
+}
+
+const wchar_t *JpgLoad::mimeType()
+{
+ return L"image/jpeg";
+}
+
+int JpgLoad::getHeaderSize()
+{
+ return 3;
+}
+
+int JpgLoad::testData( const void *data, int datalen )
+{
+ if ( datalen < 3 )
+ return 0;
+
+ const unsigned __int8 *text = static_cast<const unsigned __int8 *>( data );
+ if ( text[ 0 ] == 0xFF && text[ 1 ] == 0xD8 && text[ 2 ] == 0xFF )
+ return 1;
+
+ return 0;
+}
+/*
+struct jpeg_source_mgr {
+ const JOCTET * next_input_byte; // => next byte to read from buffer
+ size_t bytes_in_buffer; // # of bytes remaining in buffer
+
+ JMETHOD(void, init_source, (j_decompress_ptr cinfo));
+ JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo));
+ JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes));
+ JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired));
+ JMETHOD(void, term_source, (j_decompress_ptr cinfo));
+};
+*/
+
+// our reader...
+extern "C"
+{
+ static void init_source( j_decompress_ptr cinfo )
+ {}
+ static const JOCTET jpeg_eof[] = { (JOCTET)0xFF, (JOCTET)JPEG_EOI };
+ static boolean fill_input_buffer( j_decompress_ptr cinfo )
+ {
+ cinfo->src->next_input_byte = jpeg_eof;
+ cinfo->src->bytes_in_buffer = 2;
+ return TRUE;
+ }
+ static void skip_input_data( j_decompress_ptr cinfo, long num_bytes )
+ {
+ //my_src_ptr src = (my_src_ptr) cinfo->src;
+ if ( num_bytes > 0 )
+ {
+ if ( num_bytes > (long)cinfo->src->bytes_in_buffer )
+ {
+ fill_input_buffer( cinfo );
+ }
+ else
+ {
+ cinfo->src->next_input_byte += (size_t)num_bytes;
+ cinfo->src->bytes_in_buffer -= (size_t)num_bytes;
+ }
+ }
+ }
+ static void term_source( j_decompress_ptr cinfo )
+ {}
+};
+
+static void wasabi_jpgload_error_exit( j_common_ptr cinfo )
+{
+ jmp_buf *stack_env = (jmp_buf *)cinfo->client_data;
+ longjmp( *stack_env, 1 );
+}
+
+static bool IsAMG( jpeg_saved_marker_ptr marker_list )
+{
+ while ( marker_list )
+ {
+ if ( marker_list->marker == JPEG_COM && marker_list->data_length == 7 && memcmp( (const char *)marker_list->data, "AMG/AOL", 7 ) == 0 )
+ {
+ return true;
+ }
+
+ marker_list = marker_list->next;
+ }
+
+ return false;
+}
+
+ARGB32 *JpgLoad::loadImage( const void *data, int datalen, int *w, int *h, ifc_xmlreaderparams *params )
+{
+ int fail_on_amg = 0;
+
+ if ( params ) // epic failness
+ fail_on_amg = params->getItemValueInt( L"AMG", 0 );
+
+ ARGB32 *buf = 0;
+ jpeg_error_mgr jerr;
+ jpeg_decompress_struct cinfo;
+ jpeg_source_mgr src = { (const JOCTET *)data,(size_t)datalen,init_source,fill_input_buffer,skip_input_data,jpeg_resync_to_restart,term_source };
+
+ cinfo.err = jpeg_std_error( &jerr );
+
+ jpeg_create_decompress( &cinfo );
+ cinfo.src = &src;
+
+ /* set up error handling. basically C style exceptions :) */
+ jmp_buf stack_env;
+ cinfo.client_data = &stack_env;
+ cinfo.err->error_exit = wasabi_jpgload_error_exit;
+ if ( setjmp( stack_env ) )
+ {
+ // longjmp will goto here
+ jpeg_destroy_decompress( &cinfo );
+ if ( buf )
+ WASABI_API_MEMMGR->sysFree( buf );
+
+ return 0;
+ }
+
+ if ( fail_on_amg )
+ jpeg_save_markers( &cinfo, JPEG_COM, 10 );
+
+ if ( jpeg_read_header( &cinfo, TRUE ) == JPEG_HEADER_OK )
+ {
+ cinfo.out_color_space = JCS_RGB;
+ /*int ret = */jpeg_start_decompress( &cinfo );
+ if ( !fail_on_amg || !IsAMG( cinfo.marker_list ) )
+ {
+ size_t image_size = 0;
+ if ( SizeTMult( cinfo.output_width, cinfo.output_height, &image_size ) == S_OK && SizeTMult( image_size, 4, &image_size ) == S_OK )
+ {
+ buf = (ARGB32 *)WASABI_API_MEMMGR->sysMalloc( image_size );
+ int row_stride = cinfo.output_width * cinfo.output_components;
+
+ ARGB32 *p = buf;// + (cinfo.output_width * cinfo.output_height);
+
+ void* line = malloc(row_stride);
+
+ while ( cinfo.output_scanline < cinfo.output_height )
+ {
+ //p -= cinfo.output_width;
+ jpeg_read_scanlines( &cinfo, (JSAMPARRAY)&line, 1 );
+
+ unsigned char* rgb = (unsigned char*)line;
+ unsigned char* argb = (unsigned char*)p;
+ for (size_t i = 0; i < cinfo.output_width; i++)
+ {
+ argb[4 * i] = rgb[3 * i + 2];
+ argb[4 * i + 1] = rgb[3 * i + 1];
+ argb[4 * i + 2] = rgb[3 * i];
+ argb[4 * i + 3] = 0xff;
+ }
+
+
+ p += cinfo.output_width;
+ }
+ free(line);
+
+ if ( w )
+ *w = cinfo.output_width;
+
+ if ( h )
+ *h = cinfo.output_height;
+
+ jpeg_finish_decompress( &cinfo );
+ }
+ }
+ }
+
+ jpeg_destroy_decompress( &cinfo );
+
+ return buf;
+}
+
+#define CBCLASS JpgLoad
+START_DISPATCH;
+CB( ISMINE, isMine );
+CB( MIMETYPE, mimeType );
+CB( TESTDATA, testData );
+CB( GETHEADERSIZE, getHeaderSize );
+CB( LOADIMAGE, loadImage );
+END_DISPATCH;
+#undef CBCLASS \ No newline at end of file
diff --git a/Src/jpeg/loader_jpg.h b/Src/jpeg/loader_jpg.h
new file mode 100644
index 00000000..fe39192f
--- /dev/null
+++ b/Src/jpeg/loader_jpg.h
@@ -0,0 +1,23 @@
+#pragma once
+
+#include <api/service/svcs/svc_imgload.h>
+
+// {AE04FB30-53F5-4032-BD29-032B87EC3404}
+static const GUID JPEGguid =
+{ 0xae04fb30, 0x53f5, 0x4032, { 0xbd, 0x29, 0x3, 0x2b, 0x87, 0xec, 0x34, 0x04 } };
+
+
+class JpgLoad : public svc_imageLoader
+{
+public:
+ static const char *getServiceName() { return "JPEG loader"; }
+
+ static GUID getServiceGuid() { return JPEGguid; }
+ int isMine(const wchar_t *filename);
+ const wchar_t *mimeType();
+ int getHeaderSize();
+ int testData(const void *data, int datalen);
+ ARGB32 *loadImage(const void *data, int datalen, int *w, int *h, ifc_xmlreaderparams *params=NULL);
+protected:
+ RECVS_DISPATCH;
+};
diff --git a/Src/jpeg/main.h b/Src/jpeg/main.h
new file mode 100644
index 00000000..ef0bd807
--- /dev/null
+++ b/Src/jpeg/main.h
@@ -0,0 +1,6 @@
+#ifndef NULLSOFT_JPEG_MAIN_H
+#define NULLSOFT_JPEG_MAIN_H
+
+//extern bool isMMX;
+
+#endif \ No newline at end of file
diff --git a/Src/jpeg/mp4_jpeg_decoder.cpp b/Src/jpeg/mp4_jpeg_decoder.cpp
new file mode 100644
index 00000000..861d8a89
--- /dev/null
+++ b/Src/jpeg/mp4_jpeg_decoder.cpp
@@ -0,0 +1,91 @@
+#include "mp4_jpeg_decoder.h"
+#include "api__jpeg.h"
+#include <api/service/waservicefactory.h>
+
+MP4JPEGDecoder::MP4JPEGDecoder()
+{
+ jpegLoader=0;
+ width=0;
+ height=0;
+ decoded_image = 0;
+}
+
+int MP4JPEGDecoder::Open(MP4FileHandle mp4_file, MP4TrackId mp4_track)
+{
+ // load JPEG loader
+ jpegLoader = new JpgLoad;
+
+ if (jpegLoader)
+ return MP4_VIDEO_SUCCESS;
+ else
+ return MP4_VIDEO_FAILURE;
+
+}
+
+void MP4JPEGDecoder::Close()
+{
+ delete jpegLoader;
+ delete this;
+}
+
+int MP4JPEGDecoder::GetOutputFormat(int *x, int *y, int *color_format, double *aspect_ratio)
+{
+ if (!height || !width)
+ return MP4_VIDEO_FAILURE;
+
+ *x = width;
+ *y = height;
+ *color_format = '23GR'; // RGB32
+ return MP4_VIDEO_SUCCESS;
+}
+
+int MP4JPEGDecoder::DecodeSample(const void *inputBuffer, size_t inputBufferBytes, MP4Timestamp timestamp)
+{
+ bool change_in_size=false;
+ if (decoded_image)
+ WASABI_API_MEMMGR->sysFree(decoded_image);
+ int decode_width, decode_height;
+ decoded_image = jpegLoader->loadImage(inputBuffer, (int)inputBufferBytes, &decode_width, &decode_height);
+ if (!decoded_image)
+ return MP4_VIDEO_FAILURE;
+ if (width && decode_width != width // if we have a different width from last time
+ || height && decode_height != height)
+ change_in_size = true;
+
+ width = decode_width;
+ height = decode_height;
+ return change_in_size?MP4_VIDEO_OUTPUT_FORMAT_CHANGED:MP4_VIDEO_SUCCESS;
+}
+
+int MP4JPEGDecoder::CanHandleCodec(const char *codecName)
+{
+ return !strcmp(codecName, "jpeg");
+}
+
+int MP4JPEGDecoder::GetPicture(void **data, void **decoder_data, MP4Timestamp *timestamp)
+{
+ if (!decoded_image)
+ return MP4_VIDEO_FAILURE;
+
+ *data = decoded_image;
+ *decoder_data = 0;
+ decoded_image = 0; // wipe our hands clean of it so we don't double free
+ return MP4_VIDEO_SUCCESS;
+}
+
+void MP4JPEGDecoder::FreePicture(void *data, void *decoder_data)
+{
+ WASABI_API_MEMMGR->sysFree(data);
+}
+
+#define CBCLASS MP4JPEGDecoder
+START_DISPATCH;
+CB(MPEG4_VIDEO_OPEN, Open)
+CB(MPEG4_VIDEO_GETOUTPUTFORMAT, GetOutputFormat)
+CB(MPEG4_VIDEO_DECODE, DecodeSample)
+CB(MPEG4_VIDEO_HANDLES_CODEC, CanHandleCodec)
+CB(MPEG4_VIDEO_GET_PICTURE, GetPicture)
+VCB(MPEG4_VIDEO_FREE_PICTURE, FreePicture)
+END_DISPATCH;
+#undef CBCLASS
+
diff --git a/Src/jpeg/mp4_jpeg_decoder.h b/Src/jpeg/mp4_jpeg_decoder.h
new file mode 100644
index 00000000..dcb70fc1
--- /dev/null
+++ b/Src/jpeg/mp4_jpeg_decoder.h
@@ -0,0 +1,29 @@
+#include "../Plugins/Input/in_mp4/mpeg4video.h"
+#include "loader_jpg.h"
+
+// {CFF4B746-8D98-48c1-BDDF-9AA750F51517}
+static const GUID mp4_jpeg_guid =
+{ 0xcff4b746, 0x8d98, 0x48c1, { 0xbd, 0xdf, 0x9a, 0xa7, 0x50, 0xf5, 0x15, 0x17 } };
+
+
+class MP4JPEGDecoder : public MP4VideoDecoder
+{
+public:
+ static const char *getServiceName() { return "JPEG MP4 Decoder"; }
+ static GUID getServiceGuid() { return mp4_jpeg_guid; }
+ MP4JPEGDecoder();
+ int Open(MP4FileHandle mp4_file, MP4TrackId mp4_track);
+ int GetOutputFormat(int *x, int *y, int *color_format, double *aspect_ratio);
+ int DecodeSample(const void *inputBuffer, size_t inputBufferBytes, MP4Timestamp timestamp);
+ void Close();
+ int CanHandleCodec(const char *codecName);
+ int GetPicture(void **data, void **decoder_data, MP4Timestamp *timestamp);
+ void FreePicture(void *data, void *decoder_data);
+protected:
+ RECVS_DISPATCH;
+private:
+ JpgLoad *jpegLoader; // new during Open(), since we might have been created just for CanHandleCodec
+ int width, height;
+ void *decoded_image; // ARGB32
+
+}; \ No newline at end of file
diff --git a/Src/jpeg/resource.h b/Src/jpeg/resource.h
new file mode 100644
index 00000000..65e42fa2
--- /dev/null
+++ b/Src/jpeg/resource.h
@@ -0,0 +1,14 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by jpeg.rc
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/Src/jpeg/version.rc2 b/Src/jpeg/version.rc2
new file mode 100644
index 00000000..473317f5
--- /dev/null
+++ b/Src/jpeg/version.rc2
@@ -0,0 +1,39 @@
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+#include "../Winamp/buildType.h"
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION WINAMP_PRODUCTVER
+ PRODUCTVERSION WINAMP_PRODUCTVER
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "Winamp SA"
+ VALUE "FileDescription", "Winamp 5.x System Component"
+ VALUE "FileVersion", STR_WINAMP_PRODUCTVER
+ VALUE "InternalName", "jpeg.w5s"
+ VALUE "LegalCopyright", "Copyright © 2005-2023 Winamp SA"
+ VALUE "LegalTrademarks", "Nullsoft and Winamp are trademarks of Winamp SA"
+ VALUE "OriginalFilename", "jpeg.w5s"
+ VALUE "ProductName", "Winamp JPEG Image Service"
+ VALUE "ProductVersion", STR_WINAMP_PRODUCTVER
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/Src/jpeg/w5s.cpp b/Src/jpeg/w5s.cpp
new file mode 100644
index 00000000..13478e90
--- /dev/null
+++ b/Src/jpeg/w5s.cpp
@@ -0,0 +1,96 @@
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include "api__jpeg.h"
+#include "main.h"
+#include "w5s.h"
+#include "writer_jpg.h"
+#include "loader_jpg.h"
+#include "mp4_jpeg_decoder.h"
+#include "avi_mjpg_decoder.h"
+#include "../nu/Singleton.h"
+#include "../nu/factoryt.h"
+#include "amg.h"
+
+/*
+void MMXInit()
+{
+DWORD retval1, retval2;
+
+__try {
+_asm {
+mov eax, 1 // set up CPUID to return processor version and features
+// 0 = vendor string, 1 = version info, 2 = cache info
+_emit 0x0f // code bytes = 0fh, 0a2h
+_emit 0xa2
+mov retval1, eax
+mov retval2, edx
+}
+} __except(EXCEPTION_EXECUTE_HANDLER) { retval1 = retval2 = 0;}
+
+isMMX = retval1 && (retval2 & 0x800000);
+
+}
+*/
+
+static ServiceFactoryT<MP4VideoDecoder, MP4JPEGDecoder> mp4Factory;
+static ServiceFactoryT<svc_imageWriter, JpgWrite> jpegWriterFactory;
+static ServiceFactoryT<svc_imageLoader, JpgLoad> jpegLoaderFactory;
+static WA5_JPEG wa5_jpeg;
+static AMGSucks amgSucks;
+static SingletonServiceFactory<api_amgsucks, AMGSucks> amgSucksFactory;
+static AVIDecoderCreator aviCreator;
+static SingletonServiceFactory<svc_avidecoder, AVIDecoderCreator> aviFactory;
+
+//bool isMMX=false;
+
+api_service *serviceManager=0;
+api_memmgr *memoryManager=0;
+
+void WA5_JPEG::RegisterServices(api_service *service)
+{
+ //MMXInit();
+ WASABI_API_SVC = service;
+
+ // get memory manager
+ waServiceFactory *sf = WASABI_API_SVC->service_getServiceByGuid(memMgrApiServiceGuid);
+ if (sf) memoryManager = reinterpret_cast<api_memmgr *>(sf->getInterface());
+
+ WASABI_API_SVC->service_register(&jpegLoaderFactory);
+ WASABI_API_SVC->service_register(&jpegWriterFactory);
+ WASABI_API_SVC->service_register(&mp4Factory);
+ amgSucksFactory.Register(WASABI_API_SVC, &amgSucks);
+ aviFactory.Register(WASABI_API_SVC, &aviCreator);
+}
+
+int WA5_JPEG::RegisterServicesSafeModeOk()
+{
+ return 1;
+}
+
+void WA5_JPEG::DeregisterServices(api_service *service)
+{
+ service->service_deregister(&jpegWriterFactory);
+ service->service_deregister(&jpegLoaderFactory);
+ service->service_deregister(&mp4Factory);
+ amgSucksFactory.Deregister(service);
+ aviFactory.Deregister(WASABI_API_SVC);
+
+ waServiceFactory *sf = WASABI_API_SVC->service_getServiceByGuid(memMgrApiServiceGuid);
+ if (sf) sf->releaseInterface(memoryManager);
+}
+
+extern "C" __declspec(dllexport) ifc_wa5component *GetWinamp5SystemComponent()
+{
+ return &wa5_jpeg;
+}
+
+#ifdef CBCLASS
+#undef CBCLASS
+#endif
+
+#define CBCLASS WA5_JPEG
+START_DISPATCH;
+VCB(API_WA5COMPONENT_REGISTERSERVICES, RegisterServices)
+CB(15, RegisterServicesSafeModeOk)
+VCB(API_WA5COMPONENT_DEREEGISTERSERVICES, DeregisterServices)
+END_DISPATCH; \ No newline at end of file
diff --git a/Src/jpeg/w5s.h b/Src/jpeg/w5s.h
new file mode 100644
index 00000000..f3bd7f4a
--- /dev/null
+++ b/Src/jpeg/w5s.h
@@ -0,0 +1,15 @@
+#ifndef __WASABI_WA5_JPEG_H
+#define __WASABI_WA5_JPEG_H
+
+#include "../Agave/Component/ifc_wa5component.h"
+
+class WA5_JPEG : public ifc_wa5component
+{
+public:
+ void RegisterServices(api_service *service);
+ int RegisterServicesSafeModeOk();
+ void DeregisterServices(api_service *service);
+protected:
+ RECVS_DISPATCH;
+};
+#endif \ No newline at end of file
diff --git a/Src/jpeg/writer_jpg.cpp b/Src/jpeg/writer_jpg.cpp
new file mode 100644
index 00000000..7f644da4
--- /dev/null
+++ b/Src/jpeg/writer_jpg.cpp
@@ -0,0 +1,138 @@
+#include "main.h"
+#include "writer_jpg.h"
+#include "api__jpeg.h"
+
+#include <api/memmgr/api_memmgr.h>
+#include <shlwapi.h>
+#include <strsafe.h>
+
+/*BIG BIG THING TO NOTE
+I have modified jmorecfg.h line 319 to specify 4 bytes per pixel with RGB. it is normally three.
+*/
+extern "C" {
+#undef FAR
+#include "jpeglib.h"
+};
+
+JpgWrite::JpgWrite() : quality(80) {}
+
+// valid items include "quality" for jpeg files with value "0" to "100", "lossless" returns "1" if it is "0" otherwise
+// return value is 1 if the config item is supported, 0 if it is not.
+
+int JpgWrite::setConfig(const wchar_t * item, const wchar_t * value) {
+ if(!_wcsicmp(item,L"quality")) quality = _wtoi(value);
+ else return 0;
+ return 1;
+}
+
+int JpgWrite::getConfig(const wchar_t * item, wchar_t * value, int valuelen) {
+ if(!_wcsicmp(item,L"lossless")) lstrcpynW(value,L"0",valuelen);
+ else if(!_wcsicmp(item,L"quality")) StringCchPrintfW(value,valuelen,L"%d",quality);
+ else return 0;
+ return 1;
+}
+
+int JpgWrite::bitDepthSupported(int depth) {
+ if(depth == 32 || depth == 24) return 1;
+ return 0;
+}
+
+extern "C" {
+ typedef struct {
+ jpeg_destination_mgr pub;
+ BYTE *buf;
+ int len;
+ } my_destination_mgr;
+
+ void init_destination(j_compress_ptr cinfo){}
+ boolean empty_output_buffer(j_compress_ptr cinfo) {
+ my_destination_mgr* m = (my_destination_mgr*)cinfo->dest;
+ int used = m->len;
+ int d = ((m->len / 4) & 0xffffff00) + 0x100;
+ if(d < 4096) d = 4096;
+ m->len+=d;
+ m->buf = (BYTE*)WASABI_API_MEMMGR->sysRealloc(m->buf,m->len);
+ m->pub.next_output_byte = m->buf + used;
+ m->pub.free_in_buffer = d;
+
+ return TRUE;
+ }
+ void term_destination(j_compress_ptr cinfo){}
+};
+
+// returns the image in our format, free the returned buffer with api_memmgr::sysFree()
+void * JpgWrite::convert(const void *pixels, int bitDepth, int w, int h, int *length) {
+ if(bitDepth != 32 && bitDepth != 24) return 0;
+ jpeg_compress_struct cinfo={0};
+ jpeg_error_mgr jerr;
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_compress(&cinfo);
+
+ // a guess at the final size...
+ int allocsize = (int(double(w*h)*0.2) & 0xffffff00) + 0x100;
+ if (allocsize < 4096) allocsize = 4096;
+
+ // set up our output stream
+ my_destination_mgr dest = {{0,(size_t)allocsize,init_destination,empty_output_buffer,term_destination},0,allocsize};
+ dest.buf = (BYTE*)WASABI_API_MEMMGR->sysMalloc(allocsize);
+ dest.pub.next_output_byte = dest.buf;
+ cinfo.dest = (jpeg_destination_mgr*)&dest;
+
+ // image parameters
+ cinfo.image_width = w;
+ cinfo.image_height = h;
+ cinfo.input_components = 4;
+ cinfo.in_color_space = JCS_RGB;
+ jpeg_set_defaults(&cinfo);
+ jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
+ jpeg_start_compress(&cinfo, TRUE);
+
+ int row_stride = w * 4;
+
+ BYTE * scanline = (BYTE *)malloc(row_stride);
+
+ if(bitDepth == 32) {
+ const ARGB32 * p = ((const ARGB32*)pixels);// + (h * w);
+ while (cinfo.next_scanline < cinfo.image_height) {
+ //p-=w;
+ memcpy(scanline,p,row_stride);
+ for(unsigned int i=0; i < cinfo.image_width; i++)
+ ((ARGB32*)scanline)[i] = ((p[i] & 0x0000ff) << 16) | (p[i] & 0x00ff00) | ((p[i] & 0xff0000) >> 16);
+ jpeg_write_scanlines(&cinfo, &scanline, 1);
+ p+=w;
+ }
+ } else if(bitDepth == 24) { // FUCKO: untested
+ const BYTE * p = ((const BYTE*)pixels);// + (h * w * 3);
+ while (cinfo.next_scanline < cinfo.image_height) {
+ //p-=w*3;
+ memcpy(scanline,p,row_stride);
+ int l = cinfo.image_width * 4;
+ for(int i=0,j=0; j < l; i+=3,j+=4) {
+ scanline[j] = p[i+2];
+ scanline[j+1] = p[i+1];
+ scanline[j+2] = p[i];
+ }
+ jpeg_write_scanlines(&cinfo, &scanline, 1);
+ p+=w*3;
+ }
+ }
+
+ free(scanline);
+
+ jpeg_finish_compress(&cinfo);
+
+ if(length) *length = int(dest.len - dest.pub.free_in_buffer);
+ jpeg_destroy_compress(&cinfo);
+ return dest.buf;
+}
+
+#define CBCLASS JpgWrite
+START_DISPATCH;
+ CB(GETIMAGETYPENAME, getImageTypeName);
+ CB(GETEXTENSIONS, getExtensions);
+ CB(SETCONFIG, setConfig);
+ CB(GETCONFIG, getConfig);
+ CB(BITDEPTHSUPPORTED, bitDepthSupported);
+ CB(CONVERT, convert);
+END_DISPATCH;
+#undef CBCLASS \ No newline at end of file
diff --git a/Src/jpeg/writer_jpg.h b/Src/jpeg/writer_jpg.h
new file mode 100644
index 00000000..fda88e7d
--- /dev/null
+++ b/Src/jpeg/writer_jpg.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <api/service/svcs/svc_imgwrite.h>
+
+// {7BC27468-0475-4c0d-AEED-0C51195DC2EA}
+static const GUID JPEGwriteguid =
+{ 0x7bc27468, 0x475, 0x4c0d, { 0xae, 0xed, 0xc, 0x51, 0x19, 0x5d, 0xc2, 0xea } };
+
+class JpgWrite : public svc_imageWriter
+{
+public:
+ JpgWrite();
+ static const char *getServiceName() { return "JPEG writer"; }
+ static GUID getServiceGuid() { return JPEGwriteguid; }
+ const wchar_t * getImageTypeName() { return L"JPEG"; }
+ const wchar_t * getExtensions() { return L"jpg;jpeg"; }
+ int setConfig(const wchar_t * item, const wchar_t * value);
+ int getConfig(const wchar_t * item, wchar_t * value, int valuelen);
+ int bitDepthSupported(int depth);
+ void * convert(const void *pixels, int bitDepth, int w, int h, int *length);
+protected:
+ RECVS_DISPATCH;
+
+ int quality;
+};