int MP4_moov_uuid_parse(uint8_t *uuid_data, uint32_t data_len, char *title) { uint8_t *data = uuid_data; uint32_t uuid_len = read_be32(data); data += sizeof(uint32_t); if ( uuid_len != data_len ) { return 0; } //printf("uuid len = %08lx\n", uuid_len); // "MTDT" tag expected uint32_t tag = read_be32(data); if ( tag != 0x4d544454 ) { return 0; } data += sizeof(uint32_t); //printf("tag = %08lx\n", tag); if ( read_be16(data) != 0x0001 ) { return 0; } data += sizeof(uint16_t); uint16_t title_len = (read_be16(data) - 10) / 2; data += sizeof(uint16_t); if ( read_be32(data) != 0x00000001 ) { return 0; } data += sizeof(uint32_t); uint16_t lang_code = read_be16(data); data += sizeof(uint16_t); if ( read_be16(data) != 0x0001 ) { return 0; } data += sizeof(uint16_t); //printf("title len = %04lx (%d) \n", title_len, title_len); if ( title_len > (data_len - (data - uuid_data)) ) { title_len = data_len - (data - uuid_data) - 1; } for(uint16_t i = 0; i < title_len; i++) { uint16_t wc = read_be16(data); //printf("\twc=%04x\n", wc); data += sizeof(uint16_t); title[i] = (char)(wc & 0xff); } title[title_len] = 0; return 1; }
aiffStream(std::istream *_fstream) : alureStream(_fstream), format(0), dataStart(0) { ALubyte buffer[25]; int length; if(!fstream->read(reinterpret_cast<char*>(buffer), 12) || memcmp(buffer, "FORM", 4) != 0 || memcmp(buffer+8, "AIFF", 4) != 0) return; while(!dataStart || format == AL_NONE) { char tag[4]; if(!fstream->read(tag, 4)) break; /* read chunk length */ length = read_be32(fstream); if(memcmp(tag, "COMM", 4) == 0 && length >= 18) { /* mono or stereo data */ channels = read_be16(fstream); /* number of sample frames */ fstream->ignore(4); /* bits per sample */ sampleSize = read_be16(fstream) / 8; /* sample frequency */ samplerate = read_be80extended(fstream); /* block alignment */ blockAlign = channels * sampleSize; format = GetSampleFormat(channels, sampleSize*8, false); length -= 18; } else if(memcmp(tag, "SSND", 4) == 0) { dataStart = fstream->tellg(); dataStart += 8; dataLen = remLen = length - 8; } fstream->seekg(length, std::ios_base::cur); } if(dataStart > 0 && format != AL_NONE) fstream->seekg(dataStart); }
static vod_status_t mp4_decrypt_start_frame(void* ctx, input_frame_t* frame) { mp4_decrypt_state_t* state = ctx; vod_status_t rc; rc = state->frames_source->start_frame(state->frames_source_context, frame); if (rc != VOD_OK) { return rc; } // get the iv if (state->auxiliary_info_pos + MP4_AES_CTR_IV_SIZE > state->auxiliary_info_end) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "mp4_decrypt_start_frame: failed to get iv from auxiliary info"); return VOD_BAD_DATA; } mp4_aes_ctr_set_iv(&state->cipher, state->auxiliary_info_pos); state->auxiliary_info_pos += MP4_AES_CTR_IV_SIZE; if (!state->use_subsamples) { state->encrypted_bytes = UINT_MAX; return VOD_OK; } // get the subsample info if (state->auxiliary_info_pos + sizeof(uint16_t) + sizeof(cenc_sample_auxiliary_data_subsample_t) > state->auxiliary_info_end) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "mp4_decrypt_start_frame: failed to get subsample info from auxiliary info"); return VOD_BAD_DATA; } read_be16(state->auxiliary_info_pos, state->subsample_count); if (state->subsample_count <= 0) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "mp4_decrypt_start_frame: invalid subsample count"); return VOD_BAD_DATA; } read_be16(state->auxiliary_info_pos, state->clear_bytes); read_be32(state->auxiliary_info_pos, state->encrypted_bytes); state->subsample_count--; return VOD_OK; }
int mb_pa_resp_writen(mb_msg *buf, uint16_t *addr, size_t *awords) { int e; if(!buf) return(MB_ENOBUF); uint8_t fn; if((e=mb_pa_resp_fn(buf, &fn))) return(e); if(fn!=MB_FN_WRITEN) return(MB_EBADBUF); // not a writen message if((e=mb_respbuflen(buf, 8))) return(e); if((e=mb_pa_resp_checkcrc(buf))) return(e); if(addr) *addr=read_be16(buf->data+2); if(awords) *awords=read_be16(buf->data+4); return(MB_EOK); }
fluidStream(std::istream *_fstream) : alureStream(_fstream), Divisions(100), format(AL_NONE), sampleRate(48000), samplesPerTick(1.), fluidSettings(NULL), fluidSynth(NULL), fontID(FLUID_FAILED), doFontLoad(true) { if(!fsynth_handle) return; ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext()); if(device) alcGetIntegerv(device, ALC_FREQUENCY, 1, &sampleRate); char hdr[4]; if(!fstream->read(hdr, 4)) return; if(memcmp(hdr, "MThd", 4) == 0) { ALuint len = read_be32(fstream); if(len != 6) return; int type = read_be16(fstream); if(type != 0 && type != 1) return; ALuint numtracks = read_be16(fstream); Divisions = read_be16(fstream); UpdateTempo(500000); Tracks.resize(numtracks); for(std::vector<MidiTrack>::iterator i = Tracks.begin(), end = Tracks.end();i != end;i++) { if(!fstream->read(hdr, 4) || memcmp(hdr, "MTrk", 4) != 0) return; ALint len = read_be32(fstream); i->data.resize(len); if(!fstream->read(reinterpret_cast<char*>(&i->data[0]), len) || fstream->gcount() != len) return; unsigned long val = i->ReadVarLen(); i->SamplesLeft += val * samplesPerTick; } SetupSynth(); } }
// Response parsers (mb_pa_resp_*) interrogate a response datagram // First arg is always const mb_msg *buf, the datagram to decode int mb_pa_resp_checkcrc(const mb_msg *buf) { if(!buf) return(MB_ENOBUF); if(buf->len<2) return(MB_EMSHORT); int e; uint16_t crc; if((e=mb_crc16(buf, &crc))) return(e); uint16_t read_crc=read_be16(buf->data+buf->len-2); if(crc!=read_crc) return(MB_EBADBUF); return(MB_EOK); }
int mb_pa_resp_readn(mb_msg *buf, size_t words, size_t *awords, uint16_t *vals) { int e; if(!buf) return(MB_ENOBUF); uint8_t fn; if((e=mb_pa_resp_fn(buf, &fn))) return(e); if(!mb_is_fn_readn(fn)) return(MB_EBADBUF); // not a readn message if(buf->len<3) return(MB_EMSHORT); size_t nbytes=buf->data[2]; if((e=mb_respbuflen(buf, nbytes+5))) return(e); if((e=mb_pa_resp_checkcrc(buf))) return(e); if(nbytes&1) return(MB_EBADBUF); // nbytes should always be even size_t rwords=nbytes/2; if(awords) *awords=rwords; for(size_t i=0;(i<words)&&(i<rwords);i++) { if(vals) vals[i]=read_be16(buf->data+3+(i<<1)); } if(words<rwords) return(MB_EDLONG); return(MB_EOK); }
vod_status_t codec_config_avcc_get_nal_units( request_context_t* request_context, const u_char* extra_data, uint32_t extra_data_size, bool_t size_only, uint32_t* nal_packet_size_length, u_char** result, uint32_t* result_size) { const u_char* extra_data_end = extra_data + extra_data_size; const u_char* cur_pos; u_char* p; size_t actual_size; uint16_t unit_size; int unit_count; int i; if (extra_data_size < sizeof(avcc_config_t)) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "codec_config_avcc_get_nal_units: extra data size %uD too small", extra_data_size); return VOD_BAD_DATA; } *nal_packet_size_length = (((avcc_config_t*)extra_data)->nula_length_size & 0x3) + 1; // calculate total size and validate *result_size = 0; cur_pos = extra_data + sizeof(avcc_config_t); for (i = 0; i < 2; i++) // once for SPS, once for PPS { if (cur_pos >= extra_data_end) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "codec_config_avcc_get_nal_units: extra data overflow while reading unit count"); return VOD_BAD_DATA; } for (unit_count = (*cur_pos++ & 0x1f); unit_count; unit_count--) { if (cur_pos + sizeof(uint16_t) > extra_data_end) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "codec_config_avcc_get_nal_units: extra data overflow while reading unit size"); return VOD_BAD_DATA; } read_be16(cur_pos, unit_size); if (cur_pos + unit_size > extra_data_end) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "codec_config_avcc_get_nal_units: unit size %uD overflows the extra data buffer", (uint32_t)unit_size); return VOD_BAD_DATA; } cur_pos += unit_size; *result_size += sizeof(uint32_t) + unit_size; } } if (size_only) { *result = NULL; return VOD_OK; } // allocate buffer p = vod_alloc(request_context->pool, *result_size); if (p == NULL) { vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0, "codec_config_avcc_get_nal_units: vod_alloc failed"); return VOD_ALLOC_FAILED; } *result = p; // copy data cur_pos = extra_data + sizeof(avcc_config_t); for (i = 0; i < 2; i++) // once for SPS, once for PPS { for (unit_count = *cur_pos++ & 0x1f; unit_count; unit_count--) { unit_size = parse_be16(cur_pos); cur_pos += sizeof(uint16_t); *((uint32_t*)p) = 0x01000000; p += sizeof(uint32_t); vod_memcpy(p, cur_pos, unit_size); cur_pos += unit_size; p += unit_size; } } actual_size = p - *result; if (actual_size != *result_size) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "codec_config_avcc_get_nal_units: actual extra data size %uz is different than calculated size %uD", actual_size, *result_size); return VOD_UNEXPECTED; } vod_log_buffer(VOD_LOG_DEBUG_LEVEL, request_context->log, 0, "codec_config_avcc_get_nal_units: parsed extra data ", *result, *result_size); return VOD_OK; }
vod_status_t codec_config_hevc_get_nal_units( request_context_t* request_context, const u_char* extra_data, uint32_t extra_data_size, bool_t size_only, uint32_t* nal_packet_size_length, u_char** result, uint32_t* result_size) { hevc_config_t cfg; vod_status_t rc; const u_char* start_pos; const u_char* cur_pos; const u_char* end_pos; size_t actual_size; uint16_t unit_size; uint16_t count; uint8_t type_count; u_char* p; rc = codec_config_hevc_config_parse(request_context, extra_data, extra_data_size, &cfg, &start_pos); if (rc != VOD_OK) { return rc; } *nal_packet_size_length = cfg.nal_unit_size; end_pos = extra_data + extra_data_size; // calculate total size and validate *result_size = 0; cur_pos = start_pos; if (cur_pos >= end_pos) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "codec_config_hevc_get_nal_units: extra data overflow while reading type count"); return VOD_BAD_DATA; } for (type_count = *cur_pos++; type_count > 0; type_count--) { if (cur_pos + 3 > end_pos) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "codec_config_hevc_get_nal_units: extra data overflow while reading type header"); return VOD_BAD_DATA; } cur_pos++; read_be16(cur_pos, count); for (; count > 0; count--) { if (cur_pos + sizeof(uint16_t) > end_pos) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "codec_config_hevc_get_nal_units: extra data overflow while reading unit size"); return VOD_BAD_DATA; } read_be16(cur_pos, unit_size); cur_pos += unit_size; if (cur_pos > end_pos) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "codec_config_hevc_get_nal_units: extra data overflow while reading unit data"); return VOD_BAD_DATA; } *result_size += sizeof(uint32_t) + unit_size; } } if (size_only) { *result = NULL; return VOD_OK; } // allocate buffer p = vod_alloc(request_context->pool, *result_size); if (p == NULL) { vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0, "codec_config_hevc_get_nal_units: vod_alloc failed"); return VOD_ALLOC_FAILED; } *result = p; // copy data cur_pos = start_pos; for (type_count = *cur_pos++; type_count > 0; type_count--) { cur_pos++; // unit type read_be16(cur_pos, count); for (; count > 0; count--) { read_be16(cur_pos, unit_size); *((uint32_t*)p) = 0x01000000; p += sizeof(uint32_t); vod_memcpy(p, cur_pos, unit_size); p += unit_size; cur_pos += unit_size; } } // verify size actual_size = p - *result; if (actual_size != *result_size) { vod_log_error(VOD_LOG_ERR, request_context->log, 0, "codec_config_hevc_get_nal_units: actual extra data size %uz is different than calculated size %uD", actual_size, *result_size); return VOD_UNEXPECTED; } vod_log_buffer(VOD_LOG_DEBUG_LEVEL, request_context->log, 0, "codec_config_hevc_get_nal_units: parsed extra data ", *result, *result_size); return VOD_OK; }
static vod_status_t mp4_decrypt_process( mp4_decrypt_state_t* state, size_t size) { u_char* dest = state->output_pos; u_char* src = state->input_pos; vod_status_t rc; size_t cur_size; while (size > 0) { if (state->clear_bytes <= 0 && state->encrypted_bytes <= 0) { // finished a subsample, read the next one if (state->subsample_count <= 0) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "mp4_decrypt_process: exhausted subsample bytes"); return VOD_BAD_DATA; } if (state->auxiliary_info_pos + sizeof(cenc_sample_auxiliary_data_subsample_t) > state->auxiliary_info_end) { vod_log_error(VOD_LOG_ERR, state->request_context->log, 0, "mp4_decrypt_process: failed to get subsample info from auxiliary info"); return VOD_BAD_DATA; } read_be16(state->auxiliary_info_pos, state->clear_bytes); read_be32(state->auxiliary_info_pos, state->encrypted_bytes); state->subsample_count--; } if (state->clear_bytes > 0) { // copy clear bytes cur_size = vod_min(state->clear_bytes, size); dest = vod_copy(dest, src, cur_size); src += cur_size; size -= cur_size; state->clear_bytes -= cur_size; } // decrypt encrypted bytes cur_size = vod_min(state->encrypted_bytes, size); rc = mp4_aes_ctr_process(&state->cipher, dest, src, cur_size); if (rc != VOD_OK) { return rc; } dest += cur_size; src += cur_size; size -= cur_size; state->encrypted_bytes -= cur_size; } state->output_pos = dest; state->input_pos = src; return VOD_OK; }