コード例 #1
0
ファイル: tz.c プロジェクト: FranticFanatic/pennmush
static struct tzinfo *
do_read_tzfile(int fd, const char *tzfile, int time_size)
{
  struct tzinfo *tz = NULL;
  int size, n;
  bool has_64bit_times = 0;
  int isstdcnt, isgmtcnt;

  {
    char magic[5] = { '\0' };

    if (read(fd, magic, 4) != 4) {
      do_rawlog(LT_ERR, "tz: Unable to read header from %s: %s.\n", tzfile,
                strerror(errno));
      goto error;
    }

    if (memcmp(magic, TZMAGIC, 4) != 0) {
      do_rawlog(LT_ERR, "tz: %s is not a valid tzfile. Wrong magic number.\n",
                tzfile);
      goto error;
    }
  }

  {
    char version[16];
    if (read(fd, version, 16) != 16) {
      do_rawlog(LT_ERR, "tz: Unable to read chunk from %s: %s\n", tzfile,
                strerror(errno));
      goto error;
    }

    /* There's a second copy of the data using 64 bit times, following
       the chunk with 32 bit times. */
    if (version[0] == '2')
      has_64bit_times = 1;
  }

  tz = mush_malloc(sizeof *tz, "timezone");
  memset(tz, 0, sizeof *tz);

  {
    int32_t counts[6];

    READ_CHUNK(counts, sizeof counts);

    isgmtcnt = decode32(counts[0]);
    isstdcnt = decode32(counts[1]);
    tz->leapcnt = decode32(counts[2]);
    tz->timecnt = decode32(counts[3]);
    tz->typecnt = decode32(counts[4]);
    tz->charcnt = decode32(counts[5]);
  }

  /* Use 64-bit time_t version on such systems. */
  if (has_64bit_times && sizeof(time_t) == 8 && time_size == 4) {
    off_t skip = 44;            /* Header and sizes */

    skip += tz->timecnt * 5;
    skip += tz->typecnt * 6;
    skip += tz->charcnt;
    skip += tz->leapcnt * (4 + time_size);
    skip += isgmtcnt + isstdcnt;

    if (lseek(fd, skip, SEEK_SET) < 0) {
      do_rawlog(LT_ERR, "tz: Unable to seek to second section of %s: %s\n",
                tzfile, strerror(errno));
      goto error;
    }

    mush_free(tz, "timezone");
    return do_read_tzfile(fd, tzfile, 8);
  }
#define READ_TRANSITIONS(type, decode)			\
  do {							\
    type *buf;						\
    							\
    size = tz->timecnt * time_size;			\
    buf = malloc(size);						\
    READ_CHUNKF(buf, size);					\
    								\
    tz->transitions = calloc(tz->timecnt, sizeof(time_t));	\
    for (n = 0; n < tz->timecnt; n += 1)			\
      tz->transitions[n] = (time_t) decode(buf[n]);		\
    								\
    free(buf);							\
  } while (0)

  if (time_size == 4) {
    READ_TRANSITIONS(int32_t, decode32);
  } else {
    READ_TRANSITIONS(int64_t, decode64);
  }

  tz->offset_indexes = malloc(tz->timecnt);
  READ_CHUNK(tz->offset_indexes, tz->timecnt);

  {
    uint8_t *buf;
    int m, size = tz->typecnt * 6;

    buf = malloc(size);
    READ_CHUNKF(buf, size);

    tz->offsets = calloc(tz->typecnt, sizeof(struct ttinfo));

    for (n = 0, m = 0; n < tz->typecnt; n += 1, m += 6) {
      int32_t gmtoff;

      memcpy(&gmtoff, &buf[m], 4);
      tz->offsets[n].tt_gmtoff = decode32(gmtoff);
      tz->offsets[n].tt_isdst = buf[m + 4];
      tz->offsets[n].tt_abbrind = buf[m + 5];
      tz->offsets[n].tt_std = tz->offsets[n].tt_utc = 0;
    }

    free(buf);
  }

  tz->abbrevs = malloc(tz->charcnt);
  READ_CHUNK(tz->abbrevs, tz->charcnt);

#define READ_LEAPSECS(type, decode) \
  do {				    \
    type *buf;					 \
    int m, size = tz->leapcnt * (4 + time_size); \
    						 \
    buf = malloc(size);				 \
    READ_CHUNKF(buf, size);			 \
    									\
    tz->leapsecs = calloc(tz->leapcnt, sizeof(struct ttleapsecs));	\
    									\
    for (n = 0, m = 0; n < tz->leapcnt; n += 1, m += (4 + time_size)) { \
       type when;							\
      int32_t secs;							\
      									\
      memcpy(&when, buf, time_size);					\
      memcpy(&secs, buf + time_size, 4);				\
      tz->leapsecs[n].tt_when = (time_t) decode(when);			\
      tz->leapsecs[n].tt_secs = decode32(secs);				\
    }									\
    free(buf);								\
  } while (0)

  if (tz->leapcnt) {
    if (time_size == 4)
      READ_LEAPSECS(int32_t, decode32);
    else
      READ_LEAPSECS(int64_t, decode64);
  }

  {
    uint8_t *buf;
    int n;

    buf = malloc(isstdcnt);
    READ_CHUNKF(buf, isstdcnt);

    for (n = 0; n < isstdcnt; n += 1)
      tz->offsets[n].tt_std = buf[n];

    free(buf);

    buf = malloc(isgmtcnt);
    READ_CHUNKF(buf, isgmtcnt);

    for (n = 0; n < isgmtcnt; n += 1)
      tz->offsets[n].tt_utc = buf[n];

    free(buf);
  }

  return tz;

error:
  if (tz)
    free_tzinfo(tz);
  return NULL;
}
コード例 #2
0
ファイル: vorbis.c プロジェクト: Cuchulain/cinelerra
static int decode(quicktime_t *file, 
					int16_t *output_i, 
					float *output_f, 
					long samples, 
					int track, 
					int channel)
{
	int result = 0;
	int bytes;
	int i, j;
	quicktime_audio_map_t *track_map = &(file->atracks[track]);
	quicktime_trak_t *trak = track_map->track;
	quicktime_vorbis_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
	long current_position = track_map->current_position;
	long end_position = current_position + samples;
  	unsigned char *buffer;
// End of data in ogg buffer
	int eos = 0;
// End of file
	int eof = 0;
	float *pcm;
	int have_chunk = 0;


	if(samples > OUTPUT_ALLOCATION)
		printf("vorbis.c decode: can't read more than %p samples at a time.\n", OUTPUT_ALLOCATION);



	if(output_i) bzero(output_i, sizeof(int16_t) * samples);
	if(output_f) bzero(output_f, sizeof(float) * samples);







// Seeked outside output buffer's range or not initialized: restart
	if(current_position < codec->output_position - codec->output_size ||
		current_position > codec->output_position ||
		!codec->decode_initialized)
	{

		quicktime_chunk_of_sample(&codec->output_position, 
			&codec->chunk, 
			trak, 
			current_position);
// We know the first ogg packet in the chunk has a pcm_offset from the encoding.

		codec->output_size = 0;
		codec->output_end = 0;
		codec->chunk_samples = 0;



	
// Initialize and load initial buffer for decoding
		if(!codec->decode_initialized)
		{
			int init_chunk = 1;
			codec->decode_initialized = 1;

			codec->output = malloc(sizeof(float*) * track_map->channels);
			for(i = 0; i < track_map->channels; i++)
			{
				codec->output[i] = malloc(sizeof(float) * OUTPUT_ALLOCATION);
			}

			codec->output_allocated = OUTPUT_ALLOCATION;

        	ogg_sync_init(&codec->dec_oy); /* Now we can read pages */




			READ_CHUNK(init_chunk);
			init_chunk++;

   	 		if(ogg_sync_pageout(&codec->dec_oy, &codec->dec_og)!=1)
			{
				fprintf(stderr, "decode: ogg_sync_pageout: Must not be Vorbis data\n");
				return 1;
			}


    		ogg_stream_init(&codec->dec_os, ogg_page_serialno(&codec->dec_og));
    		vorbis_info_init(&codec->dec_vi);
    		vorbis_comment_init(&codec->dec_vc);

    		if(ogg_stream_pagein(&codec->dec_os, &codec->dec_og) < 0)
			{
    	  		fprintf(stderr,"decode: ogg_stream_pagein: stream version mismatch perhaps.\n");
    	  		return 1;
    		}

			if(ogg_stream_packetout(&codec->dec_os, &codec->dec_op) != 1)
			{
				fprintf(stderr, "decode: ogg_stream_packetout: Must not be Vorbis data\n");
    	  		return 1;
			}

			if(vorbis_synthesis_headerin(&codec->dec_vi, &codec->dec_vc, &codec->dec_op) < 0)
			{
				fprintf(stderr, "decode: vorbis_synthesis_headerin: not a vorbis header\n");
				return 1;
			}


			i = 0;
			while(i < 2)
			{
				while(i < 2)
				{
					result = ogg_sync_pageout(&codec->dec_oy, &codec->dec_og);
					if(result == 0) break;

					if(result == 1)
					{
						ogg_stream_pagein(&codec->dec_os, &codec->dec_og);

						while(i < 2)
						{
							result = ogg_stream_packetout(&codec->dec_os, &codec->dec_op);

							if(result == 0) break;

							if(result < 0)
							{
								fprintf(stderr, "decode: ogg_stream_packetout: corrupt secondary header\n");
								return 1;
							}

							vorbis_synthesis_headerin(&codec->dec_vi, &codec->dec_vc, &codec->dec_op);
							i++;




						}
					}
				}

				if(i < 2)
				{
					READ_CHUNK(init_chunk);
					init_chunk++;
				}

// Header should never span more than one chunk so assume it's done here
			}

			vorbis_synthesis_init(&codec->dec_vd, &codec->dec_vi);
			vorbis_block_init(&codec->dec_vd, &codec->dec_vb);

// Also the first chunk needed in decoding so don't reread after this.
			if(codec->chunk == init_chunk - 1) 
			{
				have_chunk = 1;
				codec->chunk++;
			}
		}




// Don't already have initial chunk from header
		if(!have_chunk)
		{
// Get initial chunk for decoding at new location
// From vorbisfile.c
/* clear out decoding machine state */
			ogg_stream_clear(&codec->dec_os);
			vorbis_dsp_clear(&codec->dec_vd);
			vorbis_block_clear(&codec->dec_vb);
    		ogg_sync_reset(&codec->dec_oy);

    		ogg_stream_init(&codec->dec_os, ogg_page_serialno(&codec->dec_og));
        	ogg_sync_init(&codec->dec_oy);
			vorbis_synthesis_init(&codec->dec_vd, &codec->dec_vi);
			vorbis_block_init(&codec->dec_vd, &codec->dec_vb);


			READ_CHUNK(codec->chunk);
			codec->chunk++;
			have_chunk = 1;
		}
	}

// Assume the chunk exists by now and rely on libogg to say if it's out of
// data.
	have_chunk = 1;











// Read chunks until output buffer is on or after end_position
	result = 0;
	while(codec->output_position < end_position)
	{


// Read chunk to decode if it hasn't been read yet.
		if(!have_chunk)
		{
			codec->chunk_samples = 0;

			READ_CHUNK(codec->chunk);
			if(result) break;
			codec->chunk++;
		}

		eos = 0;
		while(!eos)
		{
			result = ogg_sync_pageout(&codec->dec_oy, &codec->dec_og);







// Need more data from chunk
			if(result == 0)
			{
// End of chunk
				eos = 1;
			}
			else
// This stage checks for OggS and a checksum error.
// It doesn't tell if it's the end of a chunk.  Need to manually parse OggS
// pages to figure out how big the chunk is.
			if(result < 0)
			{
//printf("ogg_sync_pageout=-1\n");
				;
			}
			else
			{
				ogg_stream_pagein(&codec->dec_os, &codec->dec_og);



				while(!eos)
				{
//printf("decode 7\n");
					result = ogg_stream_packetout(&codec->dec_os, &codec->dec_op);

//printf("decode 8 %d\n", result);
					if(result == 0)
					{
//printf("ogg_stream_packetout=0\n");
// End of page
						eos = 1;
					}
					else
// This stage doesn't check for OggS.
					if(result < 0)
					{
//printf("ogg_stream_packetout=-1\n");
					}
					else
					{
						float **pcm;







						if(vorbis_synthesis(&codec->dec_vb, &codec->dec_op) == 0)
						{
							vorbis_synthesis_blockin(&codec->dec_vd, 
								&codec->dec_vb);
						}


						while((result = vorbis_synthesis_pcmout(&codec->dec_vd, &pcm)) > 0)
						{
//printf("vorbis_synthesis_pcmout=%x\n", result);
							for(i = 0; i < track_map->channels; i++)
							{
								float *output_channel = codec->output[i];
								float *input_channel = pcm[i];
								int k = codec->output_end;

								for(j = 0; j < result; j++)
								{
									output_channel[k++] = input_channel[j];
									if(k >= codec->output_allocated)
										k = 0;
								}
								
								if(i == track_map->channels - 1) 
									codec->output_end = k;
							}
//printf("codec->output_end = %d\n", codec->output_end);

							codec->output_position += result;
							codec->output_size += result;
							codec->chunk_samples += result;
							if(codec->output_size > codec->output_allocated)
								codec->output_size = codec->output_allocated;
							vorbis_synthesis_read(&codec->dec_vd, result);
						}
					}
//printf("decode 11\n");
				}

// Reset end of page so it isn't interpreted as an end of chunk
				eos = 0;
			}
		}


// Next chunk
		if(eos)
		{
//printf("decode 12 got=%x\n", codec->chunk_samples);
			have_chunk = 0;
		}
	}


// Fill silence
	while(codec->output_position < end_position)
	{
		for(i = 0; i < track_map->channels; i++)
			codec->output[i][codec->output_end] = 0;
		
		codec->output_end++;
		if(codec->output_end >= codec->output_allocated)
			codec->output_end = 0;
		codec->output_position++;
	}
//printf("decode 15\n");


//printf("decode 2 codec->output_position=%lld codec->output_end=%d codec->output_size=%d\n", 
//	codec->output_position, codec->output_end, codec->output_size);

	current_position = track_map->current_position;
	i = codec->output_end - (codec->output_position - current_position);
	j = 0;
	while(i < 0) i += codec->output_allocated;
	pcm = codec->output[channel];

	if(output_i)
	{
		for( ; j < samples; j++)
		{
			int sample = pcm[i] * 32767;
			CLAMP(sample, -32768, 32767);
			output_i[j] = sample;

			i++;
			if(i >= codec->output_allocated) i = 0;
		}
	}
	else
	if(output_f)
	{
		for( ; j < samples; j++)
		{
			output_f[j] = pcm[i];
			i++;
			if(i >= codec->output_allocated) i = 0;
		}
	}
//printf("decode 16\n");

	return 0;
}