/** * Takes an initialized asf_file_t structure file as a parameter. Allocates * a new asf_object_data_t in file->data and uses the file->iostream to * read all its compulsory fields into it. Notice that the actual data is * not read in any way, because we need to be able to work with non-seekable * streams as well. */ int asf_parse_data(asf_file_t *file) { asf_object_data_t *data; asf_iostream_t *iostream; uint8_t ddata[50]; int tmp; file->data = NULL; iostream = &file->iostream; /* object minimum is 24 bytes and data object needs to have * 26 additional bytes for its internal fields */ tmp = asf_byteio_read(iostream, ddata, 50); if (tmp < 0) { return tmp; } file->data = malloc(sizeof(asf_object_data_t)); data = file->data; if (!data) { return ASF_ERROR_OUTOFMEM; } /* read the object and check its size value */ asf_parse_read_object((asfint_object_t *) data, ddata); if (data->size < 50) { /* invalid size for data object */ return ASF_ERROR_INVALID_OBJECT_SIZE; } /* read data object specific compulsory fields */ GetGUID(ddata + 24, &data->file_id); data->total_data_packets = GetQWLE(ddata + 40); data->reserved = GetWLE(ddata + 48); data->packets_position = file->position + 50; /* If the file_id GUID in data object doesn't match the * file_id GUID in headers, the file is corrupted */ if (!asf_guid_equals(&data->file_id, &file->file_id)) { return ASF_ERROR_INVALID_VALUE; } /* if data->total_data_packets is non-zero (not a stream) and the data packets count doesn't match, return error */ if (data->total_data_packets && data->total_data_packets != file->data_packets_count) { return ASF_ERROR_INVALID_VALUE; } return 50; }
static void F64IDecode( void *outp, const uint8_t *in, unsigned samples ) { double *out = outp; for( size_t i = 0; i < samples; i++ ) { union { double d; uint64_t u; } s; #ifdef WORDS_BIGENDIAN s.u = GetQWLE( in ); #else s.u = GetQWBE( in ); #endif *(out++) = s.d; in += 8; } }
/** * Read next object from buffer pointed by data. Notice that * no buffer overflow checks are done! This function always * expects to have 24 bytes available, which is the size of * the object header (GUID + data size) */ static void asf_parse_read_object(asfint_object_t *obj, uint8_t *data) { GetGUID(data, &obj->guid); obj->type = asf_guid_get_type(&obj->guid); obj->size = GetQWLE(data + 16); obj->full_data = data; obj->datalen = 0; obj->data = NULL; obj->next = NULL; if (obj->type == GUID_UNKNOWN) { debug_printf("unknown object: %x-%x-%x-%02x%02x%02x%02x%02x%02x%02x%02x, %ld bytes", obj->guid.v1, obj->guid.v2, obj->guid.v3, obj->guid.v4[0], obj->guid.v4[1], obj->guid.v4[2], obj->guid.v4[3], obj->guid.v4[4], obj->guid.v4[5], obj->guid.v4[6], obj->guid.v4[7], (long) obj->size); } }
/***************************************************************************** * Lookup frame offset in index file *****************************************************************************/ static bool ReadIndexRecord( FILE *p_file, bool b_ts, int64_t i_frame, uint64_t *pi_offset, uint16_t *pi_file_num ) { uint8_t index_record[8]; if( fseek( p_file, sizeof(index_record) * i_frame, SEEK_SET ) != 0 ) return false; if( fread( &index_record, sizeof(index_record), 1, p_file ) < 1 ) return false; /* VDR usually (only?) runs on little endian machines, but VLC has a * broader audience. See recording.* in VDR source for data layout. */ if( b_ts ) { uint64_t i_index_entry = GetQWLE( &index_record ); *pi_offset = i_index_entry & UINT64_C(0xFFFFFFFFFF); *pi_file_num = i_index_entry >> 48; } else {
/** * Takes an initialized asf_file_t structure file as a parameter. Allocates * a new asf_object_index_t in file->index and uses the file->iostream to * read all its compulsory fields into it. Notice that the actual data is * not read in any way, because we need to be able to work with non-seekable * streams as well. */ int asf_parse_index(asf_file_t *file) { asf_object_index_t *index; asf_iostream_t *iostream; uint8_t idata[56]; uint64_t entry_data_size; uint8_t *entry_data = NULL; int tmp, i; file->index = NULL; iostream = &file->iostream; /* read the raw data of an index header */ tmp = asf_byteio_read(iostream, idata, 56); if (tmp < 0) { printf("Could not read index header\n"); return tmp; } /* allocate the index object */ index = malloc(sizeof(asf_object_index_t)); if (!index) { return ASF_ERROR_OUTOFMEM; } asf_parse_read_object((asfint_object_t *) index, idata); if (index->type != GUID_INDEX) { tmp = index->size; free(index); /* The guid type was wrong, just return the bytes to skip */ return tmp; } if (index->size < 56) { /* invalid size for index object */ free(index); return ASF_ERROR_INVALID_OBJECT_SIZE; } GetGUID(idata + 24, &index->file_id); index->entry_time_interval = GetQWLE(idata + 40); index->max_packet_count = GetDWLE(idata + 48); index->entry_count = GetDWLE(idata + 52); printf("INDEX\n"); printf("Total Index Entries %d\n",index->entry_count); printf("Index Size in bytes %Ld\n",index->size); printf("Index Max Packet Count %d\n",index->max_packet_count); printf("Index Entry Time Interval %Ld\n",index->entry_time_interval); if (index->entry_count == 0) { printf("Index has no entries\n"); file->index = index; return index->size; } if (index->entry_count * 6 + 56 > index->size) { free(index); return ASF_ERROR_INVALID_LENGTH; } entry_data_size = index->entry_count * 6; entry_data = malloc(entry_data_size * sizeof(uint8_t)); if (!entry_data) { free(index); return ASF_ERROR_OUTOFMEM; } tmp = asf_byteio_read(iostream, entry_data, entry_data_size); if (tmp < 0) { printf("Could not read entry data\n"); free(index); free(entry_data); return tmp; } index->entries = malloc(index->entry_count * sizeof(asf_index_entry_t)); if (!index->entries) { free(index); free(entry_data); return ASF_ERROR_OUTOFMEM; } for (i=0; i<index->entry_count; i++) { index->entries[i].packet_index = GetDWLE(entry_data + i*6); index->entries[i].packet_count = GetWLE(entry_data + i*6 + 4); } free(entry_data); file->index = index; return index->size; }
/***************************************************************************** * ProcessHeader: process OggSpots header. *****************************************************************************/ static int ProcessHeader(decoder_t* p_dec) { decoder_sys_t* p_sys = p_dec->p_sys; const uint8_t* p_extra; int i_major; int i_minor; uint64_t i_granulerate_numerator; uint64_t i_granulerate_denominator; /* The OggSpots header is always 52 bytes */ if (p_dec->fmt_in.i_extra != 52) { return VLC_EGENERIC; } p_extra = p_dec->fmt_in.p_extra; /* Identification string */ if ( memcmp(p_extra, "SPOTS\0\0", 8) ) { return VLC_EGENERIC; } /* Version number */ i_major = GetWLE(&p_extra[ 8]); /* major version num */ i_minor = GetWLE(&p_extra[10]); /* minor version num */ if (i_major != 0 || i_minor != 1) { return VLC_EGENERIC; } /* Granule rate */ i_granulerate_numerator = GetQWLE(&p_extra[12]); i_granulerate_denominator = GetQWLE(&p_extra[20]); if (i_granulerate_numerator == 0 || i_granulerate_denominator == 0) { return VLC_EGENERIC; } /* The OggSpots spec contained an error and there are implementations out * there that used the wrong value. So we detect that case and switch * numerator and denominator in that case */ if (i_granulerate_numerator == 1 && i_granulerate_denominator == 30) { i_granulerate_numerator = 30; i_granulerate_denominator = 1; } /* Normalize granulerate */ vlc_ureduce(&p_dec->fmt_in.video.i_frame_rate, &p_dec->fmt_in.video.i_frame_rate_base, i_granulerate_numerator, i_granulerate_denominator, 0); /* Image format */ if (!p_sys->b_packetizer) { if ( memcmp(&p_extra[32], "PNG", 3) && memcmp(&p_extra[32], "JPEG", 4) ) { char psz_image_type[8+1]; strncpy(psz_image_type, (char*)&p_extra[32], 8); psz_image_type[sizeof(psz_image_type)-1] = '\0'; msg_Warn(p_dec, "Unsupported image format: %s", psz_image_type); } } /* Dimensions */ p_dec->fmt_out.video.i_width = p_dec->fmt_out.video.i_visible_width = GetWLE(&p_extra[40]); p_dec->fmt_out.video.i_height = p_dec->fmt_out.video.i_visible_height = GetWLE(&p_extra[42]); /* We assume square pixels */ p_dec->fmt_out.video.i_sar_num = 1; p_dec->fmt_out.video.i_sar_den = 1; /* We don't implement background color, alignment and options at the * moment because the former doesn't seem necessary right now and the * latter are underspecified. */ if (p_sys->b_packetizer) { void* p_new_extra = realloc(p_dec->fmt_out.p_extra, p_dec->fmt_in.i_extra); if (unlikely(p_new_extra == NULL)) { return VLC_ENOMEM; } p_dec->fmt_out.p_extra = p_new_extra; p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra; memcpy(p_dec->fmt_out.p_extra, p_dec->fmt_in.p_extra, p_dec->fmt_out.i_extra); } return VLC_SUCCESS; }