jpegdec: cleanup results to use atmosphere style

This commit is contained in:
Michael Scire 2020-04-19 23:04:07 -07:00
parent 8cd7bb84e9
commit a51dd09421
6 changed files with 114 additions and 90 deletions

View File

@ -102,6 +102,7 @@ namespace ams::impl {
AMS_DEFINE_SYSTEM_THREAD(21, erpt, Main);
AMS_DEFINE_SYSTEM_THREAD(21, erpt, IpcServer);
/* jpegdec. */
AMS_DEFINE_SYSTEM_THREAD(21, jpegdec, Main);
/* pgl. */

View File

@ -20,67 +20,72 @@ namespace ams::capsrv {
R_DEFINE_NAMESPACE_RESULT_MODULE(206);
R_DEFINE_ERROR_RESULT(InvalidArgument, 2);
R_DEFINE_ERROR_RESULT(OutOfMemory, 3);
R_DEFINE_ERROR_RANGE(AlbumError, 2, 99);
R_DEFINE_ERROR_RESULT(AlbumWorkMemoryError, 3);
R_DEFINE_ERROR_RESULT(InvalidState, 7);
R_DEFINE_ERROR_RESULT(OutOfRange, 8);
R_DEFINE_ERROR_RESULT(AlbumAlreadyOpened, 7);
R_DEFINE_ERROR_RESULT(AlbumOutOfRange, 8);
R_DEFINE_ERROR_RESULT(InvalidApplicationId, 10);
R_DEFINE_ERROR_RESULT(InvalidUnknown, 11);
R_DEFINE_ERROR_RESULT(InvalidFileId, 12);
R_DEFINE_ERROR_RESULT(InvalidStorageId, 13);
R_DEFINE_ERROR_RESULT(InvalidContentType, 14);
R_DEFINE_ERROR_RANGE(AlbumInvalidFileId, 10, 19);
R_DEFINE_ERROR_RESULT(AlbumInvalidApplicationId, 11);
R_DEFINE_ERROR_RESULT(AlbumInvalidTimestamp, 12);
R_DEFINE_ERROR_RESULT(AlbumInvalidStorage, 13);
R_DEFINE_ERROR_RESULT(AlbumInvalidFileContents, 14);
R_DEFINE_ERROR_RESULT(FailedToMountImageDirectory, 21);
R_DEFINE_ERROR_RESULT(ReachedSizeLimit, 22);
R_DEFINE_ERROR_RESULT(FileInaccessible, 23);
R_DEFINE_ERROR_RESULT(InvalidFileData, 24);
R_DEFINE_ERROR_RESULT(ReachedCountLimit, 25);
R_DEFINE_ERROR_RESULT(InvalidThumbnail, 26);
R_DEFINE_ERROR_RESULT(AlbumIsNotMounted, 21);
R_DEFINE_ERROR_RESULT(AlbumIsFull, 22);
R_DEFINE_ERROR_RESULT(AlbumFileNotFound, 23);
R_DEFINE_ERROR_RESULT(AlbumInvalidFileData, 24);
R_DEFINE_ERROR_RESULT(AlbumFileCountLimit, 25);
R_DEFINE_ERROR_RESULT(AlbumFileNoThumbnail, 26);
R_DEFINE_ERROR_RESULT(BufferInsufficient, 30);
R_DEFINE_ERROR_RESULT(AlbumReadBufferShortage, 30);
R_DEFINE_ERROR_RESULT(FileReserved, 94);
R_DEFINE_ERROR_RESULT(FileReservedRead, 96);
R_DEFINE_ERROR_RANGE(AlbumFileSystemError, 90, 99);
R_DEFINE_ERROR_RANGE(AlbumAccessCorrupted, 94, 96);
R_DEFINE_ERROR_RESULT(AlbumDestinationAccessCorrupted, 96);
R_DEFINE_ERROR_RESULT(TooManyApplicationsRegistered, 820);
R_DEFINE_ERROR_RESULT(ApplicationNotRegistered, 822);
R_DEFINE_ERROR_RANGE(ControlError, 800, 899);
R_DEFINE_ERROR_RESULT(ControlResourceLimit, 820);
R_DEFINE_ERROR_RESULT(ControlNotOpened, 822);
R_DEFINE_ERROR_RESULT(DebugModeDisabled, 1023);
R_DEFINE_ERROR_RESULT(InvalidMakerNote, 1024);
R_DEFINE_ERROR_RESULT(NotSupported, 1023);
R_DEFINE_ERROR_RESULT(OutOfWorkMemory, 1212);
R_DEFINE_ERROR_RANGE(InternalError, 1024, 2047);
R_DEFINE_ERROR_RESULT(InternalJpegWorkMemoryShortage, 1212);
R_DEFINE_ERROR_RANGE(JpegMeta, 1300, 1399);
R_DEFINE_ERROR_RESULT(ContentTypeMissmatch, 1300);
R_DEFINE_ERROR_RESULT(InvalidJPEG, 1301);
R_DEFINE_ERROR_RESULT(InvalidJFIF, 1302);
R_DEFINE_ERROR_RESULT(InvalidEXIF, 1303);
R_DEFINE_ERROR_RESULT(MissingDateTime, 1304);
R_DEFINE_ERROR_RESULT(InvalidDateTimeLength, 1305);
R_DEFINE_ERROR_RESULT(DateTimeMissmatch, 1306);
R_DEFINE_ERROR_RESULT(MissingMakerNote, 1307);
R_DEFINE_ERROR_RESULT(ApplicationIdMissmatch, 1308);
R_DEFINE_ERROR_RESULT(InvalidMacHash, 1309);
R_DEFINE_ERROR_RESULT(InvalidOrientation, 1310);
R_DEFINE_ERROR_RESULT(InvalidDimension, 1311);
R_DEFINE_ERROR_RESULT(MakerNoteUnk, 1312);
R_DEFINE_ERROR_RANGE(InternalFileDataVerificationError, 1300, 1399);
R_DEFINE_ERROR_RESULT(InternalFileDataVerificationEmptyFileData, 1301);
R_DEFINE_ERROR_RESULT(InternalFileDataVerificationExifExtractionFailed, 1302);
R_DEFINE_ERROR_RESULT(InternalFileDataVerificationExifAnalyzationFailed, 1303);
R_DEFINE_ERROR_RESULT(InternalFileDataVerificationDateTimeExtractionFailed, 1304);
R_DEFINE_ERROR_RESULT(InternalFileDataVerificationInvalidDateTimeLength, 1305);
R_DEFINE_ERROR_RESULT(InternalFileDataVerificationInconsistentDateTime, 1306);
R_DEFINE_ERROR_RESULT(InternalFileDataVerificationMakerNoteExtractionFailed, 1307);
R_DEFINE_ERROR_RESULT(InternalFileDataVerificationInconsistentApplicationId, 1308);
R_DEFINE_ERROR_RESULT(InternalFileDataVerificationInconsistentSignature, 1309);
R_DEFINE_ERROR_RESULT(InternalFileDataVerificationUnsupportedOrientation, 1310);
R_DEFINE_ERROR_RESULT(InternalFileDataVerificationInvalidDataDimension, 1311);
R_DEFINE_ERROR_RESULT(InternalFileDataVerificationInconsistentOrientation, 1312);
R_DEFINE_ERROR_RESULT(TooManyFiles, 1401);
R_DEFINE_ERROR_RANGE(InternalAlbumLimitationError, 1400, 1499);
R_DEFINE_ERROR_RESULT(InternalAlbumLimitationFileCountLimit, 1401);
R_DEFINE_ERROR_RESULT(InvalidJpegHeader, 1501);
R_DEFINE_ERROR_RESULT(InvalidJpegSize, 1502);
R_DEFINE_ERROR_RANGE(InternalSignatureError, 1500, 1599);
R_DEFINE_ERROR_RESULT(InternalSignatureExifExtractionFailed, 1501);
R_DEFINE_ERROR_RESULT(InternalSignatureMakerNoteExtractionFailed, 1502);
R_DEFINE_ERROR_RESULT(SessionAllocationFailure, 1701);
R_DEFINE_ERROR_RANGE(InternalAlbumSessionError, 1700, 1799);
R_DEFINE_ERROR_RESULT(InternalAlbumLimitationSessionCountLimit, 1701);
R_DEFINE_ERROR_RANGE(TemporaryFile, 1900, 1999);
R_DEFINE_ERROR_RESULT(TemporaryFileMaxCountReached, 1901);
R_DEFINE_ERROR_RESULT(TemporaryFileOpenFailed, 1902);
R_DEFINE_ERROR_RESULT(TemporaryFileAccessFailed, 1903);
R_DEFINE_ERROR_RESULT(TemporaryFileGetCountFailed, 1904);
R_DEFINE_ERROR_RESULT(TemporaryFileSetSizeFailed, 1906);
R_DEFINE_ERROR_RESULT(TemporaryFileReadFailed, 1907);
R_DEFINE_ERROR_RESULT(TemporaryFileWriteFailed, 1908);
R_DEFINE_ERROR_RANGE(InternalAlbumTemporaryFileError, 1900, 1999);
R_DEFINE_ERROR_RESULT(InternalAlbumTemporaryFileCountLimit, 1901);
R_DEFINE_ERROR_RESULT(InternalAlbumTemporaryFileCreateError, 1902);
R_DEFINE_ERROR_RESULT(InternalAlbumTemporaryFileCreateRetryCountLimit, 1903);
R_DEFINE_ERROR_RESULT(InternalAlbumTemporaryFileOpenError, 1904);
R_DEFINE_ERROR_RESULT(InternalAlbumTemporaryFileGetFileSizeError, 1905);
R_DEFINE_ERROR_RESULT(InternalAlbumTemporaryFileSetFileSizeError, 1906);
R_DEFINE_ERROR_RESULT(InternalAlbumTemporaryFileReadFileError, 1907);
R_DEFINE_ERROR_RESULT(InternalAlbumTemporaryFileWriteFileError, 1908);
}

View File

@ -90,5 +90,8 @@
}, {
"type": "min_kernel_version",
"value": "0x0030"
}, {
"type": "handle_table_size",
"value": 16
}]
}

View File

@ -19,10 +19,25 @@
namespace ams::jpegdec::impl {
#define CAPSRV_ABORT_UNLESS(expr) { \
const bool __capsrv_assert_res = (expr); \
AMS_ASSERT(__capsrv_assert_res); \
AMS_ABORT_UNLESS(__capsrv_assert_res); \
} while (0)
#define CAPSRV_ASSERT(expr) do { \
const bool __capsrv_assert_res = (expr); \
AMS_ASSERT(__capsrv_assert_res); \
R_UNLESS(__capsrv_assert_res, capsrv::ResultAlbumError()); \
} while (0)
namespace {
constexpr const size_t LinebufferCount = 4;
constexpr const size_t ColorComponents = 3;
constexpr size_t LinebufferCount = 4;
constexpr size_t ColorComponents = 3;
constexpr int ImageSizeHorizonalUnit = 0x10;
constexpr int ImageSizeVerticalUnit = 0x4;
struct RGB {
u8 r, g, b;
@ -38,18 +53,18 @@ namespace ams::jpegdec::impl {
}
Result DecodeJpeg(DecodeOutput &out, const DecodeInput &in, u8 *work, size_t work_size) {
AMS_ASSERT(util::IsAligned(in.width, 0x10));
AMS_ASSERT(util::IsAligned(in.height, 0x4));
CAPSRV_ABORT_UNLESS(util::IsAligned(in.width, ImageSizeHorizonalUnit));
CAPSRV_ABORT_UNLESS(util::IsAligned(in.height, ImageSizeVerticalUnit));
AMS_ASSERT(out.bmp != nullptr);
AMS_ASSERT(out.bmp_size >= 4 * in.width * in.height);
CAPSRV_ABORT_UNLESS(out.bmp != nullptr);
CAPSRV_ABORT_UNLESS(out.bmp_size >= 4 * in.width * in.height);
AMS_ASSERT(out.width != nullptr);
AMS_ASSERT(out.height != nullptr);
CAPSRV_ABORT_UNLESS(out.width != nullptr);
CAPSRV_ABORT_UNLESS(out.height != nullptr);
const size_t linebuffer_size = ColorComponents * in.width;
const size_t total_linebuffer_size = LinebufferCount * linebuffer_size;
R_UNLESS(work_size >= total_linebuffer_size, capsrv::ResultOutOfWorkMemory());
R_UNLESS(work_size >= total_linebuffer_size, capsrv::ResultInternalJpegWorkMemoryShortage());
jpeg_decompress_struct cinfo;
std::memset(&cinfo, 0, sizeof(cinfo));
@ -60,7 +75,7 @@ namespace ams::jpegdec::impl {
cinfo.err = jpeg_std_error(&jerr);
jerr.error_exit = JpegErrorExit;
/* ? */
/* TODO: Here Nintendo uses setjmp, on longjmp to error ResultAlbumInvalidFileData is returned. */
jpeg_create_decompress(&cinfo);
@ -70,27 +85,22 @@ namespace ams::jpegdec::impl {
jpeg_mem_src(&cinfo, in.jpeg, in.jpeg_size);
int res = jpeg_read_header(&cinfo, true);
R_UNLESS(jpeg_read_header(&cinfo, true) == JPEG_HEADER_OK, capsrv::ResultAlbumInvalidFileData());
R_UNLESS(res == JPEG_HEADER_OK, capsrv::ResultInvalidFileData());
R_UNLESS(cinfo.image_width == in.width, capsrv::ResultInvalidFileData());
R_UNLESS(cinfo.image_height == in.height, capsrv::ResultInvalidFileData());
R_UNLESS(cinfo.image_width == in.width, capsrv::ResultAlbumInvalidFileData());
R_UNLESS(cinfo.image_height == in.height, capsrv::ResultAlbumInvalidFileData());
cinfo.out_color_space = JCS_RGB;
cinfo.dct_method = JDCT_ISLOW;
cinfo.do_fancy_upsampling = in.fancy_upsampling;
cinfo.do_block_smoothing = in.block_smoothing;
res = jpeg_start_decompress(&cinfo);
R_UNLESS(jpeg_start_decompress(&cinfo) == TRUE, capsrv::ResultAlbumInvalidFileData());
R_UNLESS(res == TRUE, capsrv::ResultInvalidFileData());
R_UNLESS(cinfo.output_width == in.width, capsrv::ResultInvalidArgument());
R_UNLESS(cinfo.output_height == in.height, capsrv::ResultInvalidArgument());
R_UNLESS(cinfo.out_color_components == ColorComponents, capsrv::ResultInvalidArgument());
R_UNLESS(cinfo.output_components == ColorComponents, capsrv::ResultInvalidArgument());
CAPSRV_ASSERT(cinfo.output_width == in.width);
CAPSRV_ASSERT(cinfo.output_height == in.height);
CAPSRV_ASSERT(cinfo.out_color_components == ColorComponents);
CAPSRV_ASSERT(cinfo.output_components == ColorComponents);
/* Pointer to output. */
RGBX *bmp = reinterpret_cast<RGBX *>(out.bmp);
@ -107,10 +117,7 @@ namespace ams::jpegdec::impl {
while (cinfo.output_scanline < cinfo.output_height) {
/* Decode scanlines. */
int parsed = jpeg_read_scanlines(&cinfo, linebuffer, 4);
/* Done! */
if (parsed == 0)
break;
CAPSRV_ASSERT(parsed <= ImageSizeVerticalUnit);
/* Line by line */
for (int index = 0; index < parsed; index++) {
@ -130,8 +137,7 @@ namespace ams::jpegdec::impl {
}
}
res = jpeg_finish_decompress(&cinfo);
R_UNLESS(res == TRUE, capsrv::ResultInvalidFileData());
R_UNLESS(jpeg_finish_decompress(&cinfo) == TRUE, capsrv::ResultAlbumInvalidFileData());
*out.width = cinfo.output_width;
*out.height = cinfo.output_height;

View File

@ -34,14 +34,14 @@ namespace ams::jpegdec {
memset(g_workmem, 0, sizeof(g_workmem));
memset(bmp, 0, bmp_size);
R_UNLESS(util::IsAligned(width, 0x10), capsrv::ResultOutOfRange());
R_UNLESS(util::IsAligned(height, 0x4), capsrv::ResultOutOfRange());
R_UNLESS(util::IsAligned(width, 0x10), capsrv::ResultAlbumOutOfRange());
R_UNLESS(util::IsAligned(height, 0x4), capsrv::ResultAlbumOutOfRange());
R_UNLESS(bmp != nullptr, capsrv::ResultBufferInsufficient());
R_UNLESS(bmp_size >= 4 * width * height, capsrv::ResultBufferInsufficient());
R_UNLESS(bmp != nullptr, capsrv::ResultAlbumReadBufferShortage());
R_UNLESS(bmp_size >= 4 * width * height, capsrv::ResultAlbumReadBufferShortage());
R_UNLESS(jpeg != nullptr, capsrv::ResultInvalidFileData());
R_UNLESS(jpeg_size != 0, capsrv::ResultInvalidFileData());
R_UNLESS(jpeg != nullptr, capsrv::ResultAlbumInvalidFileData());
R_UNLESS(jpeg_size != 0, capsrv::ResultAlbumInvalidFileData());
impl::DecodeInput decode_input = {
.jpeg = jpeg,
@ -62,14 +62,18 @@ namespace ams::jpegdec {
.bmp_size = bmp_size,
};
Result rc = impl::DecodeJpeg(decode_output, decode_input, g_workmem, sizeof(g_workmem));
/* Clear output memory on decode failure. */
/* NOTE: Nintendo does not do this. */
auto clear_guard = SCOPE_GUARD { std::memset(bmp, 0, bmp_size); };
/* Null output on failure */
if (rc.IsFailure())
memset(bmp, 0, bmp_size);
/* Decode the jpeg. */
R_TRY(impl::DecodeJpeg(decode_output, decode_input, g_workmem, sizeof(g_workmem)));
clear_guard.Cancel();
/* Clear the work memory. */
/* NOTE: Nintendo does not do this. */
std::memset(g_workmem, 0, sizeof(g_workmem));
return rc;
return ResultSuccess();
}
}

View File

@ -69,6 +69,7 @@ void __appInit(void) {
}
void __appExit(void) {
/* ... */
}
namespace {
@ -85,7 +86,11 @@ int main(int argc, char **argv)
{
/* Set thread name. */
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(jpegdec, Main));
/* Official jpegdec changes its thread priority to 21 in main. */
/* This is because older versions of the sysmodule had priority 20 in npdm. */
os::ChangeThreadPriority(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_PRIORITY(jpegdec, Main));
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(jpegdec, Main));
/* Create service. */
R_ASSERT(g_server_manager.RegisterServer<jpegdec::DecodeService>(DecodeServiceName, DecodeMaxSessions));