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 + -
显示快捷键?