After the division routines the entropy decoder was the largest part
of Monkey's Audio at the fast levels, with two things to gain.
All of its state, the range coder's and the Rice parameters, was in
statics, so each use was a load and each update a store: about half
of the function's time on ARM7TDMI, where a load is 3 cycles. Copy
it to locals for the length of a block and write it back after. The
functions that take a pointer to it have to be inlined for that to
work, and on ARMv4 gcc left the per-sample one out of line, so force
them.
The symbol was found by dividing low by help and searching the count
table for the quotient. counts[n] <= low / help is the same as
counts[n] * help <= low, so search with the multiply instead: the
first symbols are by far the likeliest. That leaves two divisions a
sample from three.
MHz for real time in perfsim's models, -c1000, -c2000 and -c3000:
Clip+ (ARMv5) 37.9, 53.8, 81.8 to 32.5, 48.4, 76.4
e200 (ARMv4) 45.3, 68.6, 111.4 to 35.2, 58.5, 101.3
A Clip+ measures 32.85 at -c1000 (61.4 before this and the division
change), with test_codec's checksum, 1008ffab, the same as the old
code's. The standalone decoder gives identical output for all four
levels tested. The path for files older than 3.98 has the same
change and was not tested, for want of a file.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Idf9002a5b5f3a423f44f70443936ea5ac427cd12
lib/arm_support/support-arm.S was written to replace libgcc's
division for ARM, and bff5a35c3c (FS#10943, 2010) added it to the
core, the plugin library and the codec library alike. When
1501df045f (2013) replaced EXTRA_LIBS with explicit lists, plugins
kept it and codecs did not, and they have taken their division from
libgcc since.
With the gcc 4.4 toolchain that cost little: its libgcc had a
routine that used clz. With gcc 9.5 libgcc has no soft-float ARMv5
variant, so ARMv5 targets get the ARMv4 routine, a shift and
subtract loop of about 130 cycles a division.
Monkey's Audio divides two or three times a sample in its range
decoder and, without codec IRAM, does it in C. On a Clip+ it is
11% to 21% slower than 3.14 was, with over half of -c1000's decode
in __udivsi3. MP2 is 4% to 7% slower.
Put libarm_support back, ahead of libgcc. In perfsim's model of
the Clip+ a division falls to 44 cycles, Monkey's Audio by 38%, 30%
and 22% at -c1000, -c2000 and -c3000 (60.9 to 37.9 MHz at -c1000),
and MP2 by 3% to 7%; nothing else moves by more than 0.6%. A Clip+
decodes -c1000 with the same checksum as before.
A division by zero in a codec goes to __div0 again, and so to the
firmware's handler, as it did with support-arm.S and with the old
libgcc (3.14's ape.codec calls it). The gcc 9.5 libgcc returns
from its own stub instead.
Change-Id: I6a9a79ce8e85bca69870349a5c0823f392a578b6
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CabbieV2 had an FM screen only for the 160x128 and 128x128 greyscale
targets. Add one for 400x240, laid out like its WPS: station art and
names where the album art and track info are, the frequency in the
progress bar, Scan/Preset, MHz and Stereo/Mono below it, and hold,
battery, volume and signal strength along the bottom.
Both screens share one backdrop, its header bar empty: each draws its
label, NOW PLAYING or FM RADIO, in Helvetica Bold rather than having it
painted into a backdrop of its own. The shuffle and repeat
placeholders, painted into the old WPS backdrop, are images drawn
while those are off.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I0331184479589cd4953bd78f4ead336f5d9b6fea
A theme's own font is converted into the build; fonts its skins load
themselves with %Fl were not, and needed the font package - or the
skin fell back to another font. Convert those as well, the way the
images a skin uses are copied with it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Ifb698f7417287954130be9b466fe3b2248c5c773
make install skipped every wps/ subfolder whose name has a dot in it:
the test meant for "." and ".." matched a dot anywhere. A theme named
with one lost its images.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Ic225960349e5d73ae4defa7524fa2cee5066e920
Entering the FM screen with no presets asks whether to scan for them.
The question and the scan clear the screen, after fms_fix_displays()
had shown the skin's backdrop, and nothing showed it again: the skin
redraws only its viewports, so the backdrop stayed missing everywhere
else - the header bar of CabbieV2's FM screen among it.
Leave the FM screen for the question and the scan and enter it again
after, as for the other screens shown from it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I7caadf3ac2a03f2825176084d8969ae6e59af471
The results were drawn right after backlight_on(), which only queues
a request to the backlight thread. lcd_update() does nothing while the
LCD is off, and the plugin then blocked waiting for a key without
updating again, so the display could keep showing the last progress
line. Refresh the display periodically while waiting for a key.
Also scroll the log up when the screen is full instead of wrapping
around to the top and overwriting old lines, which made the output
hard to read when testing a whole folder.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Regression introduced in f87ff3a9b, which made it possible for audio
playback to request a freq under 44.1KHz, instead of treating 44.1 as
a floor (and upsampling)
However, there is a report of 22KHz files playing back distorted on an
imx233 target.
IMO a 44KHz floor is reasonable, but this bug is a symptom of something
deeper. Perhaps the mp3 codec isn't doing the right thing, or there's
an issue in the pcm mixer somewhere, or the imx233 codec doesn't properly
handle 22KHz? Further investigation is warranted.
Change-Id: I751ce05f8605de7f90d3eb7b3c98873487df438b
The frame decoder reads from one flat buffer and cannot refill it, but
request_buffer() only guarantees 32KiB of contiguous data (the buffering
guard area). Frames that can be larger than that, such as high
resolution or poorly compressible streams (FLAC decoder testbench file
31), could be handed to the decoder truncated, which read past the end
of the data and lost sync.
When a request returns less than the largest frame the stream can
contain (STREAMINFO max framesize, or a bound from block size, channels
and bit depth) and it is not the end of the file, copy the frame into a
private static buffer and decode from that. Streams whose frames always
fit never touch the buffer and pay one comparison per frame. The buffer
is 64KiB, or sized for the 4608 sample blocks of memory limited targets,
and is left out entirely when MEMORYSIZE is 2MB or less.
Also fail with a codec error, instead of advancing past the data, if a
decoded frame consumed more bytes than were provided.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Change-Id: Ib4cf85ad513f8e096f73d13b4374d072e1745cb2
On colour targets the image viewer hands every file its own decoder
rejects to jpegp, including damaged ones, but jpegp barely checks its
input. Corrupt and truncated files crashed or hung it:
- At the end of the file GETC() kept returning stale bytes, so marker
searches and table reads never ended. Feed EOI markers (FF D9)
instead, which ends every loop, and stop calling read() there. This
state is reset in OPEN(): the overlay loader does not clear .bss.
- A file ending before any scan decoded as a blank image. Report it as
corrupt instead.
- Out of range header values were used as array indexes: Huffman and
conditioning table IDs, Huffman table sizes, sampling factors, scan
component counts and spectral selection. Reject them, and frames of
zero width or with no components.
- Invalid Huffman codes walked past the code length table, run lengths
wrote past coefficient 63, and huge coefficients indexed past the
IDCT clamp table. Bound all three.
- An odd DAC segment length never ended its loop.
- The coefficient buffer size could overflow an int.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I49465f38d283e159274d2f381029280cea42a8f1
- uisimulator/bitmaps/UI-samsungypcp3.bmp: the YP-CP3 from the front,
614x324, the 400x240 screen at 40,37. Dithered to RGB565: the
simulator converts its background to the 16-bit LCD format, which
turned the case's gradients into bands.
- sim-ui-defines.h: its window and screen position
- buttonmap/samsung-ypcp3.c: the YP-R0's keyboard layout - the
YP-CP3 shares its keypad - and click areas for the joystick, Back and
Menu below it, and User (Rec) and Power on the top edge above them
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I9146fd54400d85636a97509993b393bff8b1ab78
Accomplish this by checksumming the english language input
and (1) including that in binary files and (2) checking the
value matches what was compiled into the firmware image
Not sure if this is the best approach but it works.
Change-Id: I8f79ad1b9d1cdf69e6a085d7b3dd1b5e078af04b
jpegp converted every image from YCbCr, so RGB JPEGs showed scrambled
colours. That affects progressive RGB files, and now also baseline RGB
files the jpeg decoder rejects and hands on to jpegp, such as RGB with
the R component sampled 2x2.
Record the JFIF and Adobe APP14 markers, decide the colour space with
the same rule as the other decoders, and skip the YUV conversion for
RGB.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: If023eeb612b7f8a891d21fbe0070ab43c5a08f17
Both decoders treated every 3-component image as YCbCr, so RGB JPEGs
(as written by cjpeg -rgb, and by some Adobe software) came out with
wrong colours.
Decide the colour space as libjpeg does: a JFIF marker means YCbCr;
otherwise the transform flag of an Adobe APP14 marker decides (0 is
RGB); otherwise component IDs 'R', 'G', 'B' mean RGB.
Core loader: on colour targets R, G and B are stored in place in the
row buffer and the YUV conversion is skipped. Greyscale builds now
also decode G and B for RGB and combine them into luma per block,
which needs every component to be one block per MCU; other RGB
layouts are rejected there.
Plugin: RGB needs one block per MCU for every component, otherwise it
is rejected (colour targets fall back to jpegp). Colour builds convert
the R, G and B planes to YCbCr in place after decoding, so display and
greyscale view modes are unchanged; greyscale builds combine R, G and
B into luma per block as the core does.
Code size on the e200: core loader +351 bytes, plugin decoder +603
bytes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Ib24a0b7690ca4c00b3ac01b2f511309efeac5975
This allows fonts, backdrops, and wps/fms/sbs to be checked.
Note that while settings _names_ are validated, the _values_
can not always be checked. Detectable settings errors
are flagged, but are not considered fatal.
Change-Id: I2a2b7ad94462e983345a1e692eccd6bd57e90eb9
The YP-CP3 shares the YP-R0's keypad and so its plugin keymaps; with
the 400x240 screen handled every plugin builds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I516ab057c081e710cbc1cf6eca2b24ee87231244
Seven plugins have no layout or bitmaps for a 400x240 landscape
screen - the Samsung YP-CP3's, which no target building plugins has had
in that orientation. Give each the 320x240 one: the same height, and
centred in the 80 pixels more width wherever a 320x240 background has
to line up with it.
- bubbles, invadrox, rockblox: the 320x240 layout and background,
centred; the margins are cleared
- sudoku, jewels: the 320x240 bitmaps; their layouts already centre
themselves or use the width
- superdom: the 320x240 box size and board items - boxes as wide as
the screen allows make the board taller than it
- wormlet: the sizes of 320x240
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I223154da5da2250ba0f6068106ba9bec242a29ee
Five layouts define SCORENUM_Y as SCORE_Y + (...) unbracketed, so the
playfield update after each frame, PLAYFIELD_Y + 1 - SCORENUM_Y -
FONT_HEIGHT high, added that part rather than subtracting it: on a
240-line screen it ran 25 lines past the bottom. Most LCD drivers clip
it; the rk27xx one did not, and nothing in the playfield moved.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Icecf7780d81595db9d6e42125fc421cc1cb40339
The LCD controller's CSn/WEn/RDn strobes count bus clocks, set once for
1-4-1 clocks: a 120 ns write cycle at the 50 MHz bus clock, but 60 ns
when the CPU is boosted and the bus runs at 100 MHz. That is too fast
for the Samsung YP-CP3's panel: with the CPU boosted it showed stray
pixels, and partial updates left tearing behind moving things - the
boot logo too, as the firmware boosts before lcd_init().
Double the clocks while boosted, 2-8-2, which keeps the write cycle at
120 ns: set_cpu_frequency() switches them before raising the clock and
after lowering it, and lcd init picks them for the clock it runs at -
the bootloader stays at crt0's CPUFREQ_MAX.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I482073c16af39c6b1856a0e18d19a747c78975f0
lcd_update_rect() waited on the channel's CTL_L LLP_DST_EN bit, which
the last descriptor has clear: it clears when the last block is
loaded, not when it is done. The update returned with that line still
being read, and the next one reprogrammed the window and the channel
under it.
Wait for the channel to disable itself, which it does after its last
block.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Icf9314fbe40b8ea53a7f5f24ea11513e87a54cf6
lcd_update_rect() took the rect as given. One reaching past the screen
set a GRAM window off the panel, so the update showed nothing, and
built one DMA descriptor per line into scr_llp[LCD_HEIGHT] - past its
end for a rect taller than what is left of the screen. What follows
scr_llp in memory is the PCM driver's locks and then all_queues, the
kernel's queue list: a later broadcast posted to garbage.
invadrox asks for such a rect every frame. On a Samsung YP-CP3 nothing
of its playfield moved - aliens, bombs, the ship - and powering off
afterwards took a data abort in queue_post() from interrupt context.
Clip the rect to the screen, as other targets do, and do nothing if
nothing is left. Every rk27xx screen is a multiple of 4 pixels each
way, so aligning the clipped rect to 4 cannot take it past the edge.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I1f8bf865251859cd223e208a807c9a9da76a0ba0
Damaged and truncated JPEGs could make the image viewer read or write
outside its buffers:
- process_markers() trusted segment lengths, and Huffman table symbol
counts, so a segment running past the end of the file was parsed
from whatever memory followed it. Check that each marker segment,
and each Huffman table in it, lies within the file.
- A file without a complete SOS header was decoded from a NULL entropy
data pointer, as load_image() checked only for DQT and SOF. Require
SOS as well.
- img_mem() computed the image size in an int, which overflows for a
large image (a 65535x65535 file came out as 0), so the decode wrote
far past the buffer. Compute it in 64 bits and saturate.
Found with the jpeg-conformance files of the imazen codec-corpus,
which include truncated files and files from fuzzing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I1e2a9a4346fd1c0e34b0813267c6317dbf704bc7
Every program waited out its tPROG, about 0.8 ms on the Samsung
YP-CP3, before returning. Over USB mass storage that wait comes before
the status of each write command goes back to the host, and so before
the host sends the next one: nothing else runs during it.
Return once the program is started, WP# still lifted, and finish it -
wait, check the status, restore WP# - at the next chip access, or at
flash_sync(), which ftl_sync() calls. A program's result then arrives
with the next flash call; no caller checks flash_program()'s. A copy
still reports its own programs, the last one included, as the FTL
moves the data elsewhere when one fails.
On the YP-CP3 the NAND wrote at 3.64 MB/s; now 4.37 MB/s, against
4.35 MB/s in the original firmware, every read verified, also after a
power cycle.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I8de01f8be052e5d3ff06f550c614865fb1946f05
copy_sectors() copied one destination raw page at a time, so on a
two-plane part every page of a copy took two programs and two tPROG.
Its buffer already holds a page of every plane: copy that much at once,
and flash_program() programs the planes together.
Copies are most of the programs when the FTL closes blocks that random
writes left part written. Over USB mass storage on a Samsung YP-CP3 a
stress test that ran 66792 one-plane programs ran 692 now, with 43958
two-plane ones, and its program time fell from 85 s to 59 s.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Icc60d250ecc75c83c2d817efb7678333bffe3137
Every sector of a read was transferred from the chip into a controller
slot and then copied out of it, the next transfer starting only after
the copy. Start it before: it goes into the next slot, not the one
being copied.
On the Samsung YP-CP3, same test: reads at 8.25 MB/s, the original
firmware's speed, every read verified, also after a power cycle.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I53f77ea3c00bb449d772357e39602cca9c5cdba3
flash_init() sets FMWAIT to 0x1081, as the OF's FlashInit() does, and
nothing changed it after. But the OF, and the Samsung YP-CP3's NAND
bootloader, follow it with FlashTimingCfg(), at every bus clock
change: from chip 0's access time and the bus clock it derives a
timing that, for the YP-CP3's 25 ns Samsung part at 100 MHz, is 0x60
- by the RK28 controller's register layout, under half the bus cycles
per byte.
Do the same once chips are detected, for 100 MHz: the AHB runs at
CPUFREQ_MAX / 2 or slower, where the value only gains margin.
Over USB mass storage on the YP-CP3 the NAND read at 5.70 MB/s and
wrote at 3.26 MB/s; now 6.83 and 3.65 MB/s, every read verified, also
after a power cycle.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I356214c5d10e65952abc3334f5fae5deb2e02cff
usb_drv_exit() masks the UDC interrupt in the interrupt controller at
every disconnect, but only usb_init_device(), once at boot, unmasked
it. After the first unplug the UDC raised no more interrupts: on the
next plug the charging icon showed - plug detection polls VBUS_STS -
but the host's reset and requests went unanswered, so the device never
enumerated and the USB screen never came up.
Unmask it in usb_drv_init(), which runs at every connect, so that it
pairs with the mask in usb_drv_exit(). The interrupt is now masked
while USB is off, at boot too; nothing needs it then.
Tested on a Samsung YP-CP3: it enumerates at every replug.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Iab7b7e93c140990c39b0e6dfae23ffcc829f6ab2
Every sector of a write waited for the previous sector's transfer to
the chip before it was copied into a controller slot, so the copy and
the transfer never ran together. The slot the copy goes to is not the
one in transfer: copy first and wait only before the BCH engine and
the transfer restart.
On the Samsung YP-CP3, same test: 3.26 MB/s, every read verified, also
after a power cycle.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I41f43658916891a2ded74bbe21b6970f7cc78068
On a two-plane part an FTL page spans the same page of two blocks, one
in each plane, and flash_program() programmed them one after the other:
two program busy times (tPROG) per page. The original firmware's
FlashProgEnhanced() programs both with one two-plane program - 80h, the
first page, 11h, a wait of tDBSY, 81h, the second page, 10h - so the
planes share one tPROG.
Do the same where the runs of a write cover the same page of both
planes, on parts that take 81h for the second page. The original
firmware sends 80h there on Toshiba and Micron parts, which address
the planes differently too; those still program a page at a time.
enum vendor_t moves to nand-target.h for the check.
Over USB mass storage on a Samsung YP-CP3 the NAND wrote at 2.22 MB/s,
against 4.35 MB/s in the original firmware; now 2.86 MB/s, every read
verified.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I2f40e2ec426cf787b4ce452cbd0d0eb4b702e168
flash_read() latched the page afresh for every sector. The controller
streams a page from its first sector, so each sector also cost a
transfer of every sector before it in the page: reading an 8-sector
page sector by sector took 8 array loads and 36 sector transfers
instead of 1 and 8. Over USB mass storage on a Samsung YP-CP3 the
NAND read at 1.87 MB/s, against 8.25 MB/s in the original firmware.
Read each run of sectors that lie consecutively in one raw page with a
single latch. On a two-plane part a run of FTL sectors stays in one
page until it moves on to the other plane.
On the YP-CP3, same test: 5.64 MB/s, every read verified.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I9b08e56f4429ae432ccd2d2e23b9b34c18e56e97
Firmware builds reprogram the SDRAM controller twice. system_init()
sets burst 8, T_RP = T_RCD = 1 and the refresh, with CAS 3 since
a6538abd16 - CAS 2 on HM60X/HM801. And set_sdram_timing(), on every CPU
frequency change, rewrites the mode: CAS 2 whenever the AHB runs at
100 MHz or below, which is every clock this code sets.
On a generic rk2705 the firmware hangs in system_init() on those writes;
with them skipped it boots. Doing the same writes from IRAM, so that
nothing touches the SDRAM while the controller reprograms the chip,
hangs the same way: it is the settings themselves. The board's SDRAM
is an Elpida EDS1216AATA-75 (16 MB), a 133 MHz part at CAS 3 whose
minimum clock period at CAS 2 is 10 ns - exactly the 100 MHz it runs
at here, with no margin, next to minimal T_RP/T_RCD.
On a Samsung YP-CP3 the firmware boots but corrupts memory at random
once the clock first changes: data aborts on valid addresses in
unrelated code, undefined instruction exceptions on valid instructions,
glitches in the boot logo, crashes on USB plug and unplug. A memory
test over 15 MB passes with the boot's setup (CAS 3, burst 1,
T_RP = T_RCD = 2) and with system_init()'s values alike - it never
changes the clock - and skipping only the system_init() writes is not
enough, as set_sdram_timing() still selects CAS 2. With both removed
the YP-CP3 runs, passes a USB mass storage stress test and survives
USB unplug.
The boot ROM's and the bootloaders' setup works on every rk27xx target
seen, and nothing before Rockbox changes it (the NAND bootloader's
stage 1 and rk27load's s1 only probe the organisation). The gain
claimed for the tweak was a slight improvement in memory throughput.
So remove it for every rk27xx target, the HM60X/HM801 CAS 2 included,
and have set_sdram_timing() adjust only the refresh to the bus clock.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Icd063367783b0ae6eb80bad67d908269c07e704f
Every SD write failed. The card took the write command and went to
receive-data state, but never saw the block: CMD12 still found it there,
and the controller reported a missing CRC status after each block, 20
retries over. Reads worked. Stress-tested over USB mass storage on a
generic rk2705, with a SDHC card, in the normal firmware and in the
bootloader alike.
sd_init_card() switched the card to high-speed mode with CMD6. This host
is an SD 1.01 controller with a card clock of at most 25 MHz, per the
rk27xx datasheet; high speed and CMD6 came with SD 1.10, and a card
switched to it evidently does not take the data this host drives. The
original firmware never switches: after selecting the card it sets the
block length and a 1-bit bus and stays at default speed. A slower card
clock did not help; dropping the switch alone did.
Leave the card at default speed. Tested on a generic rk2705:
ums_stress.py over a 32 MiB window of the card - fill, verify, edge
sizes, a mixed read/write soak - passes at 2.3 MB/s writing and reading,
about 75% of what a 1-bit bus at 25 MHz carries.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Icfafab0bb460c8c0fda3dea455df9a36622bf764
When all three components share 1x2 or 2x1 sampling there is no chroma
subsampling, but each interleaved MCU holds two blocks per component.
The core loader assumed one chroma block per MCU, so these files (the
folder.jpg in the original report) decoded to garbage and have been
rejected since chroma sampling is validated.
Lay out the MCU generically in fix_headers(): each component's H x V
blocks in turn, with a per-block position that places chroma blocks
with the same offsets as luma. The MCU size and decode buffer now come
from the luma sampling in colour builds too, and the chroma IDCT scale
from the luma:chroma sampling ratio, which is unchanged for 1x1
chroma. The unused subsample_x/y fields are removed.
All other layouts decode byte-identically to before at every scale.
The new layouts decode byte-identically to the same image encoded as
4:4:4. Code size drops by 108 bytes on the e200 and struct jpeg by
20 bytes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I63a894d6609e56f3553a902afd6278ce70e04637
Both JPEG decoders accepted several baseline layouts they cannot decode
and produced garbage without an error:
- chroma with sampling factors other than 1x1 (the MCU layout is chosen
from luma alone, so any other chroma layout desynchronises)
- files written as more than one scan, where the first scan does not
hold every component (it was decoded as if it were interleaved)
- scans whose components are not in frame order
- a height of 0 in SOF, to be defined later by a DNL marker
Reject these in process_markers(). The imageviewer then falls back to
the jpegp decoder on colour targets, which handles all of them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Ia3373f2b934eef6e3f354b4d064faf2d89868050
Both JPEG decoders ignored the Tq selector in the frame header and
always dequantized luma with table 0 and chroma with table 1. Files
with a single shared table multiplied chroma by an empty table, and
files with separate Cb and Cr tables used the wrong one for Cr.
imageviewer/jpeg: build one dequantization table per component (3
instead of 2, +256 bytes) from the table it selects. tab_membership is
no longer used and is removed.
Core loader: the raw tables are pre-scaled in place for the IDCT, and
luma and chroma can use different IDCT scales. fix_quant_tables() now
maps each component to a table slot, copying a table that luma and
chroma share at different scales to a slot no component uses (there are
4 slots and at most 3 components, so one is always free), and rewrites
quanttable_select to that slot. No extra memory.
Selectors above 3 are rejected.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: If04c61fb0fef95da11d98d9918ea7225d8a440b0
Both JPEG decoders ignored the DC/AC table selectors in the SOS header
and always decoded luma with tables 0 and chroma with tables 1, the
layout libjpeg writes by default. Files where all components share
table 0, or where the slots are assigned differently, decoded to noise.
Look up each component's tables from its selectors instead. Baseline
JPEG only allows tables 0 and 1, which both decoders already hold, so
this needs no extra memory; selectors above 1 are rejected. In the core
loader tab_membership is no longer used and is removed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Ie1ec407ddecf1256fef410b1256b97af412fb194
The bit reader refilled from the input buffer without checking its end.
The end-of-data check in the decode loops only runs once per MCU row, so
a stream that desynchronises (or is truncated) read past the end of the
file buffer for the rest of the row. Return zero bytes past the end
instead; the pointer still advances so the per-row check stops the
decode.
Found with AddressSanitizer on a JPEG whose chroma is sampled more
densely than its luma.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Iaada1bc3cbf62b18f10fb2377c12d4d5cb9524de
config.h defines HAVE_STORAGE_FLUSH for the rk27xx Scheme A FTL when
CONFIG_STORAGE has STORAGE_NAND and CONFIG_NAND is NAND_RK27XX. sim.h
undefines CONFIG_NAND but keeps CONFIG_STORAGE, so a simulator for a
NAND target - the iPod nano 2G - evaluated the undefined macro:
"CONFIG_NAND" is not defined, evaluates to 0 [-Wundef]
Test that it is defined first.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Id1e328f08c14d7c5528d29f110fdbb8be68ab2f5