Reverse-engineered implementation of Ingenic Media Platform (IMP) libraries based on Binary Ninja MCP decompilations of libimp.so v1.1.6 for T31 platform.
OpenIMP is no longer blocked on basic pipeline plumbing. The active blocker is now narrow and specific:
- the AVPU runs
- interrupts fire
- frames advance
- streams are queued and released correctly
- periodic IDRs appear
- but the hardware still writes no entropy-coded payload bytes after the software-prewritten H.264 headers
Current symptom on device:
- P-frames:
len=14,NALs: 9 1,nz_after_hdr=0 - IDR frames:
len=47,NALs: 9 7 8 5,nz_after_hdr=0
This means the header path is substantially closer to OEM, but the final entropy/payload-write stage is still not at parity.
From the latest logs.txt capture:
- live Enc2 CL logging is working
- repeated P-frame Enc2 submissions show stable values:
cmd[0x1b]=0x00070c80cmd[0x1c]=0x21230904cmd[0x1d]=0x00027000cmd[0x1e]=0x14000007
- P-frames still end as header-only stubs:
raw_end=14,annexb=14,nz_after_hdr=0
- GOP-based periodic IDR cadence is working:
- example: frame
200emitsNALs: 9 7 8 5 - but the IDR is still header-only:
len=47,nz_after_hdr=0
- example: frame
-
The old capture/refcount stall is fixed
- frames continue advancing far past the earlier stall point
- interrupts/completions remain live
-
Stream lifecycle bugs are no longer the main blocker
- completed stream buffers rotate correctly
- the exact completed buffer is returned and released
-
Periodic IDR scheduling now works
- logs show scheduled refresh points and
NALs: 9 7 8 5
- logs show scheduled refresh points and
-
Header generation and splice bookkeeping are at least partially correct
- P path:
AUD + slice header - IDR path:
AUD + SPS + PPS + IDR slice header
- P path:
-
The remaining failure is specifically “no payload after header”
nz_after_hdr=0raw_end == hdr_offset- no nonzero bytes appear after the software-prewritten header window
-
Enc2 word structure is closer to OEM than before
SliceParamToCmdRegsEnc2was decompiled and the code now uses OEM-shaped packers forcmd[0x1b],cmd[0x1c], andcmd[0x1d]
-
cmd[0x1d]is likely no longer the main bug- current submitted value matches the recovered 640x360 OEM shape:
0x00027000
- current submitted value matches the recovered 640x360 OEM shape:
-
cmd[0x1b]is probably okay for the current baseline case- live submitted value matches the known-good stock value:
0x00070c80
- live submitted value matches the known-good stock value:
-
All runtime slice fields feeding
cmd[0x1c]are correct- layout is improved and the 640x360 baseline P-frame word now matches the stock/live shape, but some late OEM field producers are still inferred rather than fully recovered
-
Post-CL register block parity is complete
0x8400–0x8428is much closer to OEM, but still not proven complete for active P-frame entropy submission
cmd[0x1e]is not fully explained yet
SliceParamToCmdRegsEnc2andGenerateAvcSliceHeaderrecovered the word layout and the+0xf8/+0x100producers, butUpdateCommandstill owns a late runtime producer forSliceParam+0xfc
SliceParam+0x66is likely picture-command-driven
AL_ApplyPictCommandscopies command payload bytes at offsets0x66and0x67into encoder runtime state under picture-command flag0x400, which is a stronger lead than the older static entropy-mode guesses
| Topic | Confidence | Why |
|---|---|---|
| Capture/refcount stall fixed | High | Frames advance; IRQ/completion path stays live |
| Stream buffer ownership/lifecycle fixed | High | Completed buffers rotate and release correctly |
| Periodic IDR cadence fixed | High | Logs show NALs: 9 7 8 5 |
| Header generation/splice path mostly correct | High | AU headers are structured correctly for P and IDR |
| Failure is payload-write specific | High | nz_after_hdr=0 and raw_end==hdr_offset repeatedly |
cmd[0x1b] parity for 640x360 baseline |
Medium-High | Live value matches stock shape |
cmd[0x1d] parity |
Medium-High | Live value matches recovered OEM formula |
cmd[0x1c] fully correct |
Medium-Low | P-frame shape matches stock/live, but some producers remain inferred |
cmd[0x1e] fully explained |
Low | +0xf8/+0x100 are proven; +0xfc still depends on UpdateCommand |
SliceParam+0x66 source identified |
Low-Medium | AL_ApplyPictCommands points to picture-command state, but the exact state slot is still unmapped |
0x8400–0x8428 post-CL parity complete |
Low-Medium | Still a plausible remaining mismatch area |
| Working AVPU H.264 parity is close | Medium | The remaining failure surface is much smaller, but still blocking payload |
Recover the remaining runtime-produced slice fields that feed Enc2,
especially the fields that ultimately land in cmd[0x1c], the picture-command
state behind SliceParam+0x66, and the unresolved UpdateCommand -> SliceParam+0xfc producer behind cmd[0x1e].
Most likely OEM sources:
UpdateCommandGenerateAvcSliceHeaderCmdRegsEnc1ToSliceParamSliceParamToCmdRegsEnc2AL_ApplyPictCommands
Re-check the post-CL register/config block for the active P-frame entropy path, especially around:
0x8400–0x8428- header offset alignment
- stream-part windowing
- ordering relative to
CL_PUSH=8
We should consider the AVPU path meaningfully unblocked when logs show:
nz_after_hdr > 0raw_end > hdr_offset- P-frames longer than 14 bytes
- IDRs longer than header-only 47 bytes
- decoder-visible payload rather than only
NALs: 9 1or header-only9 7 8 5
The remainder of CURRENT_STATUS.md is older, broader implementation history.
It is still useful for module-level context, but the section above is the most
accurate summary of the current OEM-parity blocker.
- Library Size: 125KB (libimp.a), 88KB (libimp.so)
- Total Lines: 4,313 lines of implementation code
- Last Updated: 2026-04-03
- Build Status: ✅ Compiles cleanly with minor warnings
- Modules: 10 modules implemented
- Build Status: ✅ Compiles cleanly with only minor warnings
- Status: COMPLETE
- Features:
- Real kernel driver integration via /dev/mem and /dev/jz-dma
- DMABuffer structure (0x94 bytes) with safe member access
- IMP_Alloc/IMP_PoolAlloc/IMP_Free with actual mmap()
- ioctl commands: IOCTL_MEM_ALLOC, IOCTL_MEM_FREE, IOCTL_MEM_GET_PHY, IOCTL_MEM_FLUSH
- Fallback to posix_memalign() if kernel unavailable
- Thread-safe with mutex protection
- Physical/virtual address mapping
- Size: ~280 lines of code
- Based on: Decompilation at 0x99acc
- Status: COMPLETE
- Features:
- frame_capture_thread() polls kernel driver
- ioctl VIDIOC_POLL_FRAME (0x400456bf) for frame availability
- Gets frames from VBM pool
- Integrated with IMP_FrameSource_EnableChn/DisableChn
- Proper thread lifecycle (create on enable, cancel on disable)
- Safe struct member access with memcpy()
- Integration: Runs continuously when channel is enabled
- Status: COMPLETE
- Features:
- encoder_thread() - Processes frames through codec
- stream_thread() - Retrieves encoded streams
- eventfd signaling between threads
- AL_Codec_Encode_Process() integration
- AL_Codec_Encode_GetStream() integration
- Proper thread synchronization with select()
- Integration: Threads created in IMP_Encoder_CreateChn
- Based on: Decompilations at 0x1a920, 0x1aa54, 0x1b388
- Status: COMPLETE
- Features:
- Observer structure for module binding
- add_observer() - Add observer to list
- remove_observer() - Remove observer from list
- notify_observers() - Notify all observers with frame
- BindObserverToSubject() - Bind two modules
- system_bind() - Internal bind implementation
- IMP_System_RegisterModule() - Register module in global registry
- Integration: Ready for FrameSource -> Encoder binding
- Based on: Decompilations at 0x7af28, 0x7b254, 0x7b384
- Status: COMPLETE
- Features:
- Thread-safe queue with mutex, condition variable, semaphore
- Timeout support (infinite, no-wait, timed)
- Abort flag for graceful shutdown
- Proper initialization and cleanup
- Size: 64 bytes structure, ~280 lines of code
- Based on: Decompilation at 0x1efe4
- Status: COMPLETE (core functions)
- Features:
- VBMCreatePool with 12+ pixel format support
- Frame size calculation for NV12, RGB, YUV, etc.
- Memory allocation via IMP_Alloc/IMP_PoolAlloc
- Physical/virtual address management
- Global frame volume tracking (30 entries)
- VBMDestroyPool, VBMFillPool, VBMFlushFrame, VBMGetFrame, VBMReleaseFrame
- Structures:
- VBMPool: 0x180 + (bufcount * 0x428) bytes
- VBMFrame: 0x428 bytes per frame
- VBMVolume: Global array for frame tracking
- Based on: Decompilations at 0x7950c, 0x7a180, 0x790b8, etc.
- Status: COMPLETE (core functions)
- Features:
- AL_Codec_Encode_Create/Destroy
- AL_Codec_Encode_SetDefaultParam (full parameter initialization)
- AL_Codec_Encode_GetSrcFrameCntAndSize
- AL_Codec_Encode_GetSrcStreamCntAndSize
- AL_Codec_Encode_Process (frame queuing)
- AL_Codec_Encode_GetStream/ReleaseStream
- Dual FIFO system for frames and streams
- Structure: 0x924 bytes (AL_CodecEncode)
- Size: ~350 lines of code
- Based on: Decompilations at 0x1b01c, 0x1b1e0, etc.
- Status: COMPLETE
- Features:
- Module structure (0x148+ bytes) with exact offsets
- g_modules[6][6] global registry at 0x108ca0
- Observer pattern binding mechanism
- Timestamp system with CLOCK_MONOTONIC
- CPU ID mapping for 24 Ingenic platforms
- IMP_System_Init/Exit
- IMP_System_Bind/UnBind
- IMP_System_GetVersion
- Based on: Decompilations at 0x836e0, 0x80b40, etc.
- Status: COMPLETE (core functions)
- Features:
- EncChannel structure (0x308 bytes) with exact offsets
- g_EncChannel[9] global array
- IMP_Encoder_CreateChn (full implementation)
- IMP_Encoder_DestroyChn
- IMP_Encoder_RegisterChn/UnRegisterChn
- IMP_Encoder_StartRecvPic/StopRecvPic
- Encoder and stream threads (basic loop)
- 3 semaphores, 2 mutexes (one recursive)
- Event FD creation
- Frame buffer allocation
- Size: ~775 lines of code
- Based on: Decompilations at 0x9ecf8, 0x9ed84, etc.
- Status: COMPLETE (core functions)
- Features:
- FSChannel structure (0x2e8 bytes)
- IMP_FrameSource_CreateChn/DestroyChn
- IMP_FrameSource_SetChnAttr/GetChnAttr
- IMP_FrameSource_EnableChn/DisableChn (with kernel driver integration)
- IMP_FrameSource_GetFrame/ReleaseFrame
- Device operations via /dev/framechan%d
- Size: ~400 lines of code
- Based on: FrameSource decompilations
- Status: COMPLETE (core ioctls)
- Features:
- 6 ioctl commands:
- 0x407056c4 (GET_FMT)
- 0xc07056c3 (SET_FMT)
- 0xc0145608 (SET_BUFCNT)
- 0x800456c5 (SET_DEPTH)
- 0x80045612 (STREAM_ON)
- 0x80045613 (STREAM_OFF)
- Device open with retry logic (257 retries, 10ms delay)
- VBM implementation
- 6 ioctl commands:
- Size: ~550 lines of code
- Based on: Audio decompilations
- Status: COMPLETE (structure and lifecycle)
- Features:
- AudioDevice structure (0x260 bytes)
- AudioChannel structure (0x208 bytes)
- IMP_AI_SetPubAttr/GetPubAttr
- IMP_AI_Enable/Disable
- IMP_AI_EnableChn/DisableChn
- IMP_AI_PollingFrame/GetFrame/ReleaseFrame
- Size: ~350 lines of code
- Based on: OSD decompilations
- Status: COMPLETE (structure and lifecycle)
- Features:
- OSDRegion structure (0x38 bytes)
- Free/used region lists
- IMP_OSD_CreateGroup/DestroyGroup
- IMP_OSD_CreateRgn/DestroyRgn
- IMP_OSD_RegisterRgn/UnRegisterRgn
- IMP_OSD_SetRgnAttr/GetRgnAttr
- IMP_OSD_ShowRgn/HideRgn
- Size: ~400 lines of code
- Status: STUB (basic structure only)
- Size: ~100 lines of code
- Status: STUB (basic structure only)
- Size: ~70 lines of code
- Build System: Clean compilation, proper linking
- Thread Safety: Proper mutex/semaphore/condition variable usage
- Memory Management: Proper allocation/deallocation
- Module System: Registration, binding, lifecycle
- Encoder: Channel creation with full initialization
- FrameSource: Device operations, format control
- VBM: Frame buffer management
- Fifo: Thread-safe queuing
- Codec: Parameter initialization, frame/stream queuing
- IMP_Alloc/IMP_Free: Need actual kernel driver calls for DMA memory
- Physical memory mapping: mmap() integration
- VBM frame queuing: Actual buffer exchange with kernel driver
- FrameSource capture: Real frame capture from /dev/framechan%d
- Encoder thread: Actual frame encoding loop
- Get frames from FrameSource via binding
- Process through codec
- Handle frame timing
- Stream thread: Actual stream output handling
- Get encoded streams from codec
- Queue for IMP_Encoder_GetStream
- Handle stream release
- IMP_Encoder_GetStream: Full implementation (decompiled at 0x84c5c)
- IMP_Encoder_ReleaseStream: Full implementation (decompiled at 0x85508)
- AL_Encoder_Create: Actual hardware encoder initialization
- AL_Encoder_Process: Real encoding via hardware
- AL_Encoder_Destroy: Hardware cleanup
- Buffer pools: Actual DMA buffer management
- PixMap pools: Frame buffer management
- Observer notifications: Actual data flow between modules
- Frame passing: FrameSource → Encoder data path
- Buffer management: Shared buffer pools
- Full ISP implementation
- Tuning daemon integration
- Algorithm threads
- Intelligent video surveillance functions
- Motion detection
- Object tracking
- 0x00: name[16]
- 0x40: bind_func
- 0x44: unbind_func
- 0x58: observer_list
- 0xe4: sem_e4
- 0xf4: sem_f4
- 0x104: thread
- 0x108: mutex
- 0x130: group_id
- 0x00: chn_id
- 0x08: codec
- 0x0c: src_frame_cnt
- 0x10: src_frame_size
- 0x14: frame_buffers
- 0x18: fifo[64]
- 0x98: attr
- 0x1d8: mutex_1d8
- 0x1f0: cond_1f0
- 0x220: eventfd
- 0x398: registered
- 0x3ac: started
- 0x400: recv_pic_enabled
- 0x404: recv_pic_started
- 0x408: sem_408
- 0x418: sem_418
- 0x428: sem_428
- 0x438: mutex_438
- 0x450: mutex_450 (recursive)
- 0x468: thread_encoder
- 0x46c: thread_stream
- 0x00: chn_id
- 0x1c: state
- 0x1c4: fd
- 0x1c8: attr
- 0x000: g_pCodec
- 0x004: codec_param[0x794]
- 0x798: encoder
- 0x79c: event
- 0x7a0: callback
- 0x7a4: callback_arg
- 0x7a8: channel_id
- 0x7ac: stream_buf_count
- 0x7b0: stream_buf_size
- 0x7f8: fifo_frames[64]
- 0x81c: fifo_streams[64]
- 0x840: frame_buf_count
- 0x8dc: frame_buf_size
- 0x918: src_fourcc
- 0x920: metadata_type
-
Implement IMP_Alloc/IMP_Free with kernel driver
- Find /dev/mem or /dev/ipu device
- Implement mmap() for physical memory
- Integrate with VBM
-
Implement IMP_Encoder_GetStream/ReleaseStream
- Based on decompilations at 0x84c5c, 0x85508
- Stream queue management
- Semaphore-based blocking
-
Implement encoder/stream threads
- Frame capture from FrameSource
- Actual encoding loop
- Stream output handling
-
Test with prudynt-t
- Validate API compatibility
- Test actual streaming
- Debug issues
-
Implement remaining codec functions
- Hardware encoder integration
- Buffer pool management
- Metadata handling
- Unit Tests: Test individual functions
- Integration Tests: Test module interactions
- prudynt-t: Real-world application testing
- Hardware Tests: Actual encoding on T31 device
IMPLEMENTATION_PROGRESS.md: Detailed progress trackingREVERSE_ENGINEERING_SUMMARY.md: Technical summaryBINARY_ANALYSIS.md: Binary analysis findingsSESSION_SUMMARY.md: Session summariesCURRENT_STATUS.md: This file
We have successfully implemented the core infrastructure and most API functions based on actual binary decompilations. The architecture is correct, data structures match the binary exactly, and the API is fully compatible. The remaining work is primarily hardware integration and actual encoding logic.
This is a true reverse-engineered implementation, not a stub library! 🎯