/*unsigned*/ /*uint*/ int calc_lc_bits(frame_header_t hdr) { switch (hdr.codec) { case 0: return(16); case 1: case 2: case 3: if (hdr.stream_id == 0) { return(12); } else { return(16); } case 10: case 13: return(12); default: throw new Exception("unknown codec field " + hdr.codec); return(16); } }
void parse_header(byte *buf, frame_header_t hdr) { hdr.codec = buf[8] & 0xf; hdr.stream_id = (buf[8] >> 4) & 0x3; hdr.pdu_seq = (buf[8] >> 6) | ((buf[9] & 1) << 2); hdr.blend_control = (buf[9] >> 1) & 0x3; hdr.per_stream_delay = buf[9] >> 3; hdr.common_delay = buf[10] & 0x3f; hdr.latency = (buf[10] >> 6) | ((buf[11] & 1) << 2); hdr.pfirst = ((buf[11] >> 1) & 1) != 0; hdr.plast = ((buf[11] >> 2) & 1) != 0; hdr.seq = (buf[11] >> 3) | ((buf[12] & 1) << 5); hdr.nop = (buf[12] >> 1) & 0x3f; hdr.hef = buf[12] >> 7; hdr.la_location = buf[13]; }
void frame_process(int length) { /*unsigned*/ /*uint*/ int offset = 0; /*unsigned*/ /*uint*/ int audio_end = length; if (has_fixed()) { audio_end = process_fixed_data(length); } while (offset < audio_end - RS_CODEWORD_LEN) { /*unsigned*/ /*uint*/ int start = offset; /*unsigned*/ /*uint*/ int j, lc_bits, loc_bytes, prog; /*unsigned*/ short[] locations = new short[MAX_AUDIO_PACKETS]; frame_header_t hdr = new frame_header_t(); hef_t hef = new hef_t(); if (fix_header(this.buffer + offset) == 0) { // go back to coarse sync if we fail to decode any audio packets in a P1 frame if (length == MAX_PDU_LEN && offset == 0) { sync.syncState = SYNC_STATE.SYNC_STATE_NONE; } return; } parse_header(this.buffer + offset, hdr); offset += 14; lc_bits = calc_lc_bits(hdr); loc_bytes = ((lc_bits * hdr.nop) + 4) / 8; if (start + hdr.la_location < offset + loc_bytes || start + hdr.la_location >= audio_end) { return; } for (j = 0; j < hdr.nop; j++) { locations[j] = (short)parse_location(this.buffer + offset, lc_bits, j); if (j == 0 && locations[j] <= hdr.la_location) { return; } if (j > 0 && locations[j] <= locations[j - 1]) { return; } if (start + locations[j] >= audio_end) { return; } } offset += loc_bytes; if (hdr.hef != 0) { offset += parse_hef(this.buffer + offset, audio_end - offset, hef); } prog = hef.prog_num; parse_hdlc(aas_push, this.psd_buf[prog], ref this.psd_idx[prog], MAX_AAS_LEN, this.buffer + offset, start + hdr.la_location + 1 - offset); offset = start + hdr.la_location + 1; for (j = 0; j < hdr.nop; ++j) { /*unsigned*/ /*uint*/ int cnt = start + locations[j] - offset; if (crc8(this.buffer + offset, cnt + 1) != 0) { Console.WriteLine("crc mismatch!"); offset += cnt + 1; continue; } if (j == 0 && hdr.pfirst) { if (this.pdu_idx[prog] != 0) { Utils.Memcpy(this.pdu[prog] + this.pdu_idx[prog], this.buffer + offset, cnt); input_pdu_push(this.pdu[prog], cnt + this.pdu_idx[prog], prog); } else { Console.WriteLine("ignoring partial pdu"); } } else if (j == hdr.nop - 1 && hdr.plast) { Utils.Memcpy(this.pdu[prog], this.buffer + offset, cnt); this.pdu_idx[prog] = cnt; } else { input_pdu_push(this.buffer + offset, cnt, prog); } offset += cnt + 1; } } }