summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libmkv/nut-3.c110
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++) {