util.c

来自「这个库实现了录象功能」· C语言 代码 · 共 941 行 · 第 1/2 页

C
941
字号
/******************************************************************************* util.c libquicktime - A library for reading and writing quicktime/avi/mp4 files. http://libquicktime.sourceforge.net Copyright (C) 2002 Heroine Virtual Ltd. Copyright (C) 2002-2007 Members of the libquicktime project. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA*******************************************************************************/ #include "lqt_private.h"#include "lqt_fseek.h"#include "workarounds.h"#include <sys/stat.h>#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <time.h>#include <math.h>#ifndef HAVE_LRINT#define lrint(x) ((long int)(x))#endif/* Disk I/O */int64_t quicktime_get_file_length(const char *path){      struct stat status;      if(stat(path, &status))              perror("quicktime_get_file_length stat:");      return status.st_size;}int quicktime_file_open(quicktime_t *file, const char *path, int rd, int wr){	int exists = 0;	char flags[10];	if(rd && (file->stream = fopen(path, "rb")))	{		exists = 1; 		fclose(file->stream); 	}	if(rd && !wr) sprintf(flags, "rb");	else	if(!rd && wr) sprintf(flags, "wb");	else	if(rd && wr)	{		if(exists) 			sprintf(flags, "rb+");		else			sprintf(flags, "wb+");	}	if(!(file->stream = fopen(path, flags)))	{		return 1;	}	if(rd && exists)	{		file->total_length = quicktime_get_file_length(path);			}        if(wr)          file->presave_buffer = calloc(1, QUICKTIME_PRESAVE);		return 0;}int quicktime_file_close(quicktime_t *file){/* Flush presave buffer */        if(file->presave_size)        {                quicktime_fseek(file, file->presave_position - file->presave_size);                fwrite(file->presave_buffer, 1, file->presave_size, file->stream);                file->presave_size = 0;        }         if(file->stream)        {                fclose(file->stream);        }        file->stream = 0;        return 0;}int64_t quicktime_ftell(quicktime_t *file){	return file->ftell_position;}int quicktime_fseek(quicktime_t *file, int64_t offset){	file->ftell_position = offset;	if(offset > file->total_length || offset < 0) return 1;	if(fseeko(file->stream, file->ftell_position, SEEK_SET))	{//		perror("quicktime_fseek fseeko");		return 1;	}	return 0;}/* Read entire buffer from the preload buffer */static int read_preload(quicktime_t *file, uint8_t *data, int64_t size){	int64_t selection_start = 0;	int64_t selection_end = 0;	int64_t fragment_start = 0;	int64_t fragment_len = 0;	selection_start = file->file_position;	selection_end = quicktime_add(file->file_position, size);	fragment_start = file->preload_ptr + (selection_start - file->preload_start);	while(fragment_start < 0) fragment_start += file->preload_size;	while(fragment_start >= file->preload_size) fragment_start -= file->preload_size;	while(selection_start < selection_end)	{		fragment_len = selection_end - selection_start;		if(fragment_start + fragment_len > file->preload_size)			fragment_len = file->preload_size - fragment_start;		memcpy(data, file->preload_buffer + fragment_start, fragment_len);		fragment_start += fragment_len;		data += fragment_len;		if(fragment_start >= file->preload_size) fragment_start = (int64_t)0;		selection_start += fragment_len;	}	return 0;}int quicktime_read_data(quicktime_t *file, uint8_t *data, int64_t size)  {  int result = 1;  /* Return if we had an error before */  if(file->io_error || file->io_eof)    return 0;    if(!file->preload_size)    {    quicktime_fseek(file, file->file_position);    result = fread(data, 1, size, file->stream);    if(result < size)      {      file->io_error = ferror(file->stream);      file->io_eof   = feof(file->stream);      }    file->ftell_position += size;    }  else    {    /* Region requested for loading */    int64_t selection_start = file->file_position;    int64_t selection_end = file->file_position + size;    int64_t fragment_start, fragment_len;    if(selection_end - selection_start > file->preload_size)      {      /* Size is larger than preload size.  Should never happen. */      quicktime_fseek(file, file->file_position);      result = fread(data, 1, size, file->stream);      if(result < size)        {        file->io_error = ferror(file->stream);        file->io_eof   = feof(file->stream);        }      file->ftell_position += size;      }    else if(selection_start >= file->preload_start &&             selection_start < file->preload_end &&            selection_end <= file->preload_end &&            selection_end > file->preload_start)      {      /* Entire range is in buffer */      read_preload(file, data, size);      result = size;      }    else if(selection_end > file->preload_end &&             selection_end - file->preload_size < file->preload_end)      {      /* Range is after buffer */      /* Move the preload start to within one preload length of the selection_end */      while(selection_end - file->preload_start > file->preload_size)        {        fragment_len = selection_end - file->preload_start - file->preload_size;        if(file->preload_ptr + fragment_len > file->preload_size)           fragment_len = file->preload_size - file->preload_ptr;        file->preload_start += fragment_len;        file->preload_ptr += fragment_len;        if(file->preload_ptr >= file->preload_size) file->preload_ptr = 0;        }            /* Append sequential data after the preload end to the new end */      fragment_start = file->preload_ptr + file->preload_end - file->preload_start;      while(fragment_start >= file->preload_size)         fragment_start -= file->preload_size;            while(file->preload_end < selection_end)        {        fragment_len = selection_end - file->preload_end;        if(fragment_start + fragment_len > file->preload_size)          fragment_len = file->preload_size - fragment_start;        quicktime_fseek(file, file->preload_end);        result = fread(&(file->preload_buffer[fragment_start]),                       fragment_len, 1, file->stream);        if(result < fragment_len)          {          file->io_error = ferror(file->stream);          file->io_eof   = feof(file->stream);          }        file->ftell_position += fragment_len;        file->preload_end += fragment_len;        fragment_start += fragment_len;        if(fragment_start >= file->preload_size)          fragment_start = 0;        }            read_preload(file, data, size);      result = size;      }    else      {      /* Range is before buffer or over a preload_size away from the end of the buffer. */      /* Replace entire preload buffer with range. */      quicktime_fseek(file, file->file_position);      result = fread(file->preload_buffer, 1, size, file->stream);      if(result < size)        {        file->io_error = ferror(file->stream);        file->io_eof   = feof(file->stream);        }      file->ftell_position += size;      file->preload_start = file->file_position;      file->preload_end = file->file_position + size;      file->preload_ptr = 0;      read_preload(file, data, size);            }    }  file->file_position += size;  return result;  }int quicktime_write_data(quicktime_t *file, const uint8_t *data, int size)  {  int data_offset = 0;  int writes_attempted = 0;  int writes_succeeded = 0;  if(file->io_error)    return 0;    // Flush existing buffer and seek to new position  if(file->file_position != file->presave_position)    {    if(file->presave_size)      {      quicktime_fseek(file, file->presave_position - file->presave_size);      writes_succeeded += fwrite(file->presave_buffer, 1, file->presave_size, file->stream);      writes_attempted += file->presave_size;      file->presave_size = 0;      }    file->presave_position = file->file_position;    }  // Write presave buffers until done  while(size > 0)    {    int fragment_size = QUICKTIME_PRESAVE;    if(fragment_size > size) fragment_size = size;    if(fragment_size + file->presave_size > QUICKTIME_PRESAVE)      fragment_size = QUICKTIME_PRESAVE- file->presave_size;    memcpy(file->presave_buffer + file->presave_size,           data + data_offset,           fragment_size);    file->presave_position += fragment_size;    file->presave_size += fragment_size;    data_offset += fragment_size;    size -= fragment_size;    if(file->presave_size >= QUICKTIME_PRESAVE)      {      quicktime_fseek(file, file->presave_position - file->presave_size);      writes_succeeded += fwrite(file->presave_buffer, 1, file->presave_size, file->stream);      writes_attempted += file->presave_size;      file->presave_size = 0;      }    }  /* Adjust file position */  file->file_position = file->presave_position;  /* Adjust ftell position */  file->ftell_position = file->presave_position;  /* Adjust total length */  if(file->total_length < file->ftell_position) file->total_length = file->ftell_position;  /* fwrite failed */  if(!writes_succeeded && writes_attempted)    {    file->io_error = ferror(file->stream);    return 0;    }  else    if(!size)      return 1;    else      return size;  }int64_t quicktime_byte_position(quicktime_t *file){	return quicktime_position(file);}void quicktime_read_pascal(quicktime_t *file, char *data){	char len = quicktime_read_char(file);	quicktime_read_data(file, (uint8_t*)data, len);	data[(int)len] = 0;}void quicktime_write_pascal(quicktime_t *file, char *data){	uint8_t len = strlen(data);	quicktime_write_data(file, &len, 1);	quicktime_write_data(file, (uint8_t*)data, len);}float quicktime_read_fixed32(quicktime_t *file){	unsigned long a, b, c, d;	uint8_t data[4];	quicktime_read_data(file, data, 4);	a = data[0];	b = data[1];	c = data[2];	d = data[3];		a = (a << 8) + b;	b = (c << 8) + d;	if(b)		return (float)a + (float)b / 65536;	else		return a;}int quicktime_write_fixed32(quicktime_t *file, float number){	unsigned char data[4];	int a, b;	a = number;	b = (number - a) * 65536;	data[0] = a >> 8;	data[1] = a & 0xff;	data[2] = b >> 8;		data[3] = b & 0xff;	return quicktime_write_data(file, data, 4);}static floatfloat32_be_read (unsigned char *cptr){       int             exponent, mantissa, negative ;        float   fvalue ;        negative = cptr [0] & 0x80 ;        exponent = ((cptr [0] & 0x7F) << 1) | ((cptr [1] & 0x80) ? 1 : 0) ;        mantissa = ((cptr [1] & 0x7F) << 16) | (cptr [2] << 8) | (cptr [3]) ;        if (! (exponent || mantissa))                return 0.0 ;        mantissa |= 0x800000 ;        exponent = exponent ? exponent - 127 : 0 ;        fvalue = mantissa ? ((float) mantissa) / ((float) 0x800000) : 0.0 ;        if (negative)                fvalue *= -1 ;        if (exponent > 0)                fvalue *= (1 << exponent) ;        else if (exponent < 0)                fvalue /= (1 << abs (exponent)) ;        return fvalue ;} /* float32_be_read */static doubledouble64_be_read (unsigned char *cptr){       int             exponent, negative ;        double  dvalue ;        negative = (cptr [0] & 0x80) ? 1 : 0 ;        exponent = ((cptr [0] & 0x7F) << 4) | ((cptr [1] >> 4) & 0xF) ;        /* Might not have a 64 bit long, so load the mantissa into a double. */        dvalue = (((cptr [1] & 0xF) << 24) | (cptr [2] << 16) | (cptr [3] << 8) | cptr [4]) ;        dvalue += ((cptr [5] << 16) | (cptr [6] << 8) | cptr [7]) / ((double) 0x1000000) ;        if (exponent == 0 && dvalue == 0.0)                return 0.0 ;        dvalue += 0x10000000 ;        exponent = exponent - 0x3FF ;        dvalue = dvalue / ((double) 0x10000000) ;        if (negative)                dvalue *= -1 ;        if (exponent > 0)                dvalue *= (1 << exponent) ;        else if (exponent < 0)                dvalue /= (1 << abs (exponent)) ;        return dvalue ;} /* double64_be_read */static voidfloat32_be_write (float in, unsigned char *out){       int             exponent, mantissa, negative = 0 ;        memset (out, 0, sizeof (int)) ;        if (in == 0.0)                return ;        if (in < 0.0)        {       in *= -1.0 ;                negative = 1 ;                } ;        in = frexp (in, &exponent) ;        exponent += 126 ;        in *= (float) 0x1000000 ;        mantissa = (((int) in) & 0x7FFFFF) ;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?