diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-02-18 17:06:38 -0700 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-02-18 17:06:38 -0700 |
commit | 7e02069e19666e29a3ccefb0b7107e5cd9c49cc3 (patch) | |
tree | e85ba18af4e4902cfcbc69b7e61bf0820ee5846b | |
parent | a40f9a84922b752a69a255c8eab1ba20ee7e754e (diff) |
wip
-rw-r--r-- | libmkv/nut-3.c | 110 |
1 files changed, 42 insertions, 68 deletions
diff --git a/libmkv/nut-3.c b/libmkv/nut-3.c index 2acf3ac..2bd552d 100644 --- a/libmkv/nut-3.c +++ b/libmkv/nut-3.c @@ -232,11 +232,9 @@ struct app_state { #define APP_COMMON_FLAGS NUT_FRAMEFLAG_KEY|NUT_FRAMEFLAG_SIZE_MSB|NUT_FRAMEFLAG_CHECKSUM|NUT_FRAMEFLAG_SM_DATA -#define APP_SIZE_MSB_MUL 0x2000 /* must be less than 0x4000 */ +#define APP_FRAME_SIZE_MSB_MUL 0x2000 /* must be less than 0x4000 */ -#define _APP_ELIDE_640_480 19 -#define _APP_ELIDE_720_480 19 -#define _APP_ELIDE_720_576 19 +#define APP_SM_SIZE 19 #define _APP_W_640_480 640 #define _APP_W_720_480 720 #define _APP_W_720_576 720 @@ -244,13 +242,12 @@ struct app_state { #define _APP_H_720_480 480 #define _APP_H_720_576 576 -#define APP_ELIDE(res) LM_CAT2_(_APP_ELIDE_, res) #define APP_W(res) LM_CAT2_(_APP_W_, res) #define APP_H(res) LM_CAT2_(_APP_H_, res) -#define APP_FB(res) (APP_W(res)*APP_H(res)/2) -#define APP_SIZE(res) (APP_ELIDE(res)+APP_FB(res)) -/* HERE */ -#define APP_FRAME_MAX_OVERHEAD 31 +#define APP_FB_SIZE(res) (APP_W(res)*APP_H(res)/2) +#define APP_FRAME_SIZE(res) (APP_SM_SIZE+APP_FB_SIZE(res)) + +#define APP_FRAME_MAX_OVERHEAD (31+APP_SM_SIZE) bool app_write_intro(int fd, struct app_state *state, uint64_t time_ns) { assert(state); @@ -264,9 +261,6 @@ bool app_write_intro(int fd, struct app_state *state, uint64_t time_ns) { /* Changing resolution mid-stream requires per-fame side-data, * which requires FLAG_SM_DATA, which requires NUT v4. * - * If we're pulling in NUT v4 for that, we can also take - * advantage of header elision. - * * Unfortunately, libnut / nututils does not support v4, so * there goes a good debugging tool. */ @@ -275,11 +269,13 @@ bool app_write_intro(int fd, struct app_state *state, uint64_t time_ns) { #define BOGUS 0 pkt.len = 0; + /* head *******************************************/ nut_append_vu(&pkt, 4); /*! version */ nut_append_vu(&pkt, 0); /*! minor_version */ nut_append_vu(&pkt, 1); /*! stream_count */ - nut_append_vu(&pkt, APP_FB(720_576) + /*! max_distance */ + nut_append_vu(&pkt, APP_FB_SIZE(720_576) + /*! max_distance */ APP_FRAME_MAX_OVERHEAD); + /* time bases *************************************/ nut_append_vu(&pkt, 1); /*! time_base_count */ @@ -300,10 +296,10 @@ bool app_write_intro(int fd, struct app_state *state, uint64_t time_ns) { nut_append_vu(&pkt, APP_COMMON_FLAGS); /*! flags */ nut_append_vu(&pkt, 8); /*! field_count */ nut_append_vu(&pkt, BOGUS); /*! 0: fields.pts */ - nut_append_vu(&pkt, APP_SIZE_MSB_MUL); /*! 1: fields.size_msb_nul */ + nut_append_vu(&pkt, APP_FRAME_SIZE_MSB_MUL); /*! 1: fields.size_msb_nul */ nut_append_vu(&pkt, 0); /*! 2: fields.stream */ - nut_append_vu(&pkt, APP_SIZE(640_480) % /*! 3: fields.size_lsb */ - APP_SIZE_MSB_MUL); + nut_append_vu(&pkt, APP_FRAME_SIZE(640_480) % /*! 3: fields.size_lsb */ + APP_FRAME_SIZE_MSB_MUL); nut_append_vu(&pkt, 0); /*! 4: fields.reserved */ nut_append_vu(&pkt, 1); /*! 5: fields.count */ nut_append_vs(&pkt, NUT_UNKNOWN_MATCH_TIME); /*! 6: fields.match */ @@ -313,10 +309,10 @@ bool app_write_intro(int fd, struct app_state *state, uint64_t time_ns) { nut_append_vu(&pkt, APP_COMMON_FLAGS); /*! flags */ nut_append_vu(&pkt, 8); /*! field_count */ nut_append_vu(&pkt, BOGUS); /*! 0: fields.pts */ - nut_append_vu(&pkt, APP_SIZE_MSB_MUL); /*! 1: fields.size_msb_mul */ + nut_append_vu(&pkt, APP_FRAME_SIZE_MSB_MUL); /*! 1: fields.size_msb_mul */ nut_append_vu(&pkt, 0); /*! 2: fields.stream */ - nut_append_vu(&pkt, APP_SIZE(720_480) % /*! 3: fields.size_lsb */ - APP_SIZE_MSB_MUL); + nut_append_vu(&pkt, APP_FRAME_SIZE(720_480) % /*! 3: fields.size_lsb */ + APP_FRAME_SIZE_MSB_MUL); nut_append_vu(&pkt, 0); /*! 4: fields.reserved */ nut_append_vu(&pkt, 1); /*! 5: fields.count */ nut_append_vs(&pkt, NUT_UNKNOWN_MATCH_TIME); /*! 6: fields.match */ @@ -326,10 +322,10 @@ bool app_write_intro(int fd, struct app_state *state, uint64_t time_ns) { nut_append_vu(&pkt, APP_COMMON_FLAGS); /*! flags */ nut_append_vu(&pkt, 8); /*! field_count */ nut_append_vu(&pkt, BOGUS); /*! 0: fields.pts */ - nut_append_vu(&pkt, APP_SIZE_MSB_MUL); /*! 1: fields.size_msb_nul */ + nut_append_vu(&pkt, APP_FRAME_SIZE_MSB_MUL); /*! 1: fields.size_msb_nul */ nut_append_vu(&pkt, 0); /*! 2: fields.stream */ - nut_append_vu(&pkt, APP_SIZE(720_576) % /*! 3: fields.size_lsb */ - APP_SIZE_MSB_MUL); + nut_append_vu(&pkt, APP_FRAME_SIZE(720_576) % /*! 3: fields.size_lsb */ + APP_FRAME_SIZE_MSB_MUL); nut_append_vu(&pkt, 0); /*! 4: fields.reserved */ nut_append_vu(&pkt, 1); /*! 5: fields.count */ nut_append_vs(&pkt, NUT_UNKNOWN_MATCH_TIME); /*! 6: fields.match */ @@ -341,41 +337,9 @@ bool app_write_intro(int fd, struct app_state *state, uint64_t time_ns) { nut_append_vu(&pkt, BOGUS); /*! 0: fields.pts */ nut_append_vu(&pkt, 256-4-1); /*! 1: fields.size_msb_nul */ - /* elision headers ********************************/ - nut_append_vu(&pkt, 3); /*! header_count_minus_1 */ - - /* elision_header[1] (640x480) */ - hdr.len = 0; - nut_append_vu(&hdr, 2); /*! side_data_count */ - nut_append_vb_str(&hdr, "Width"); /*! side_data[0].name */ - nut_append_vu(&hdr, APP_W(640_480)); /*! side_data[0].value */ - nut_append_vb_str(&hdr, "Height"); /*! side_data[1].name */ - nut_append_vu(&hdr, APP_H(640_480)/2); /*! side_data[1].value */ - nut_append_vu(&hdr, 0); /*! meta_data_count */ - assert(hdr.len == APP_ELIDE(640_480)); - nut_append_vb(&pkt, hdr.dat, hdr.len); - - /* elision_header[2] (720x480) */ - hdr.len = 0; - nut_append_vu(&hdr, 2); /*! side_data_count */ - nut_append_vb_str(&hdr, "Width"); /*! side_data[0].name */ - nut_append_vu(&hdr, APP_W(720_480)); /*! side_data[0].value */ - nut_append_vb_str(&hdr, "Height"); /*! side_data[1].name */ - nut_append_vu(&hdr, APP_H(720_480)/2); /*! side_data[1].value */ - nut_append_vu(&hdr, 0); /*! meta_Data_count */ - assert(hdr.len == APP_ELIDE(720_480)); - nut_append_vb(&pkt, hdr.dat, hdr.len); - - /* elision_header[3] (720x576) */ - hdr.len = 0; - nut_append_vu(&hdr, 2); /*! side_data_count */ - nut_append_vb_str(&hdr, "Width"); /*! side_data[0].name */ - nut_append_vu(&hdr, APP_H(720_576)); /*! side_data[0].value */ - nut_append_vb_str(&hdr, "Height"); /*! side_data[1].name */ - nut_append_vu(&hdr, APP_H(720_576)/2); /*! side_data[1].value */ - nut_append_vu(&hdr, 0); /*! meta_data_count */ - assert(hdr.len == APP_ELIDE(720_576)); - nut_append_vb(&pkt, hdr.dat, hdr.len); + /* tail *******************************************/ + nut_append_vu(&pkt, 0); /*! header_count_minus_1 */ + nut_append_vu(&pkt, 0); /*! main_flags */ nut_append_packet(&out, nut_startcode_main, pkt.dat, pkt.len); #undef BOGUS @@ -421,27 +385,37 @@ bool app_write_frame(int fd, struct app_state *state, uint64_t time_ns, enum app struct buf pkt = {0}; uint64_t beg = state->len; - size_t full_size, fb_size; + size_t frame_size, fb_size; switch (res) { - case APP_RES_640_480: full_size = APP_SIZE(640_480); fb_size = APP_FB(640_480); break; - case APP_RES_720_480: full_size = APP_SIZE(720_480); fb_size = APP_FB(720_480); break; - case APP_RES_720_576: full_size = APP_SIZE(720_576); fb_size = APP_FB(720_576); break; + case APP_RES_640_480: frame_size = APP_FRAME_SIZE(640_480); fb_size = APP_FB_SIZE(640_480); break; + case APP_RES_720_480: frame_size = APP_FRAME_SIZE(720_480); fb_size = APP_FB_SIZE(720_480); break; + case APP_RES_720_576: frame_size = APP_FRAME_SIZE(720_576); fb_size = APP_FB_SIZE(720_576); break; } - /* packet (syncpoint) ( (8+1)+ (10+2) + 4 = 25 bytes) */ + /* packet (syncpoint) ( (8+1)+(10+2)+4 = 25 bytes) */ nut_append_vu(&pkt, time_ns); /*! global_key_pts (<=10 bytes) */ nut_append_vu(&pkt, state->last_syncpoint ? (beg - state->last_syncpoint)/16 : 0); /*! back_ptr_div16 (<=2 bytes) */ nut_append_packet(&out, nut_startcode_syncpoint, pkt.dat, pkt.len); /* frame header ( 1+1+4 = 6 bytes) */ uint64_t frame_beg = out.len; - nut_append_u8(&out, 1+res); /*! frame_code (4 byte) */ - nut_append_vu(&out, full_size/APP_SIZE_MSB_MUL); /*! data_size_msb (1 byte) */ - nut_append_u32(&out, nut_crc32(&out.dat[frame_beg], out.len - frame_beg)); /*! checksum (4 bytes) */ - /* side_data and meta_data come from elision headers */ + nut_append_u8(&out, 1+res); /*! frame_code (4 bytes) */ + nut_append_vu(&out, frame_size/APP_FRAME_SIZE_MSB_MUL); /*! data_size_msb (1 byte) */ + nut_append_u32(&out, nut_crc32(&out.dat[frame_beg], out.len - frame_beg)); /*! checksum (4 bytes) */ - /* flush */ assert(out.len <= APP_FRAME_MAX_OVERHEAD); + + /* side/meta data ( 1+(6+2)+(7+2)+1 = 19 bytes) */ + uint64_t data_beg = out.len; + nut_append_vu(&out, 2); /*! side_data_count (1 byte) */ + nut_append_vb_str(&out, "Width"); /*! side_data[0].name (1+5 bytes) */ + nut_append_vu(&out, APP_W(720_480)); /*! side_data[0].value (2 bytes) */ + nut_append_vb_str(&out, "Height"); /*! side_data[1].name (1+6 bytes) */ + nut_append_vu(&out, APP_H(720_480)/2); /*! side_data[1].value (2 bytes) */ + nut_append_vu(&out, 0); /*! meta_data_count (1 byte) */ + assert(out.len - data_beg == APP_SM_SIZE); + + /* flush */ bool err = xwrite(fd, out.dat, out.len); free(out.dat); free(pkt.dat); @@ -521,7 +495,7 @@ int main() { if (app_write_intro(1, &state, 0)) return 1; - uint8_t framebuffer[APP_FB(720_576)]; + uint8_t framebuffer[APP_FB_SIZE(720_576)]; #define SCALE 10 for (int i = 0; i < 10; i++) { |