Update to latest libasf (r107)

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37363 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
David McPaul
2010-07-03 06:12:56 +00:00
parent a775c1a432
commit affec393bc
21 changed files with 533 additions and 603 deletions
@@ -184,9 +184,9 @@ ASFFileReader::getVideoFormat(uint32 streamIndex, ASFVideoFormat *format)
format->extraData = videoHeader->data;
if (stream->flags & ASF_STREAM_FLAG_EXTENDED) {
format->FrameScale = stream->extended->avg_time_per_frame;
format->FrameScale = stream->extended_properties->avg_time_per_frame;
format->FrameRate = 10000000L;
printf("num avg time per frame for video %Ld\n",stream->extended->avg_time_per_frame);
printf("num avg time per frame for video %Ld\n",stream->extended_properties->avg_time_per_frame);
}
return true;
@@ -210,9 +210,9 @@ ASFFileReader::getStreamDuration(uint32 streamIndex)
if (stream) {
if (stream->flags & ASF_STREAM_FLAG_EXTENDED) {
printf("STREAM %ld end time %Ld, start time %Ld\n",streamIndex, stream->extended->end_time, stream->extended->start_time);
if (stream->extended->end_time - stream->extended->start_time > 0) {
return stream->extended->end_time - stream->extended->start_time;
printf("STREAM %ld end time %Ld, start time %Ld\n",streamIndex, stream->extended_properties->end_time, stream->extended_properties->start_time);
if (stream->extended_properties->end_time - stream->extended_properties->start_time > 0) {
return stream->extended_properties->end_time - stream->extended_properties->start_time;
}
}
}
@@ -6,9 +6,7 @@ StaticLibrary libasfreader.a :
asf.c
byteio.c
data.c
fileio.c
guid.c
header.c
parse.c
utf.c
;
@@ -1,5 +1,5 @@
/* libasf - An Advanced Systems Format media file parser
* Copyright (C) 2006-2007 Juho Vähä-Herttua
* Copyright (C) 2006-2010 Juho Vähä-Herttua
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -21,13 +21,31 @@
#include "asf.h"
#include "asfint.h"
#include "fileio.h"
#include "byteio.h"
#include "header.h"
#include "parse.h"
#include "data.h"
#include "debug.h"
static int
asf_fileio_read_cb(void *stream, void *buffer, int size)
{
int ret;
ret = fread(buffer, 1, size, stream);
if (!ret && !feof(stream))
return -1;
return ret;
}
static int64_t
asf_fileio_seek_cb(void *stream, int64_t offset)
{
return fseek(stream, offset, SEEK_SET);
}
asf_file_t *
asf_open_file(const char *filename)
{
@@ -35,12 +53,12 @@ asf_open_file(const char *filename)
asf_iostream_t stream;
FILE *fstream;
fstream = fopen(filename, "r");
fstream = fopen(filename, "rb");
if (!fstream)
return NULL;
stream.read = asf_fileio_read_cb;
stream.write = asf_fileio_write_cb;
stream.write = NULL;
stream.seek = asf_fileio_seek_cb;
stream.opaque = fstream;
@@ -80,7 +98,7 @@ asf_open_cb(asf_iostream_t *iostream)
file->streams[i].type = ASF_STREAM_TYPE_NONE;
file->streams[i].flags = ASF_STREAM_FLAG_NONE;
file->streams[i].properties = NULL;
file->streams[i].extended = NULL;
file->streams[i].extended_properties = NULL;
}
return file;
@@ -96,7 +114,7 @@ asf_init(asf_file_t *file)
tmp = asf_parse_header(file);
if (tmp < 0) {
printf("error parsing header: %d\n", tmp);
debug_printf("error parsing header: %d", tmp);
return tmp;
}
file->position += tmp;
@@ -104,7 +122,7 @@ asf_init(asf_file_t *file)
tmp = asf_parse_data(file);
if (tmp < 0) {
printf("error parsing data object: %d\n", tmp);
debug_printf("error parsing data object: %d", tmp);
return tmp;
}
file->position += tmp;
@@ -124,7 +142,7 @@ asf_init(asf_file_t *file)
file->index_position < file->file_size && !file->index) {
tmp = asf_parse_index(file);
if (tmp < 0) {
printf("Error finding index object! %d\n", tmp);
debug_printf("Error finding index object! %d", tmp);
break;
}
@@ -152,7 +170,7 @@ asf_init(asf_file_t *file)
for (tmp = 0; tmp < ASF_MAX_STREAMS; tmp++) {
if (file->streams[tmp].type != ASF_STREAM_TYPE_NONE) {
debug_printf("stream %d of type %s found!", tmp, file->streams[tmp].type == 1 ? "Audio" : file->streams[tmp].type == 2 ? "Video" : "Unknown");
debug_printf("stream %d of type %d found!", tmp, file->streams[tmp].type);
}
}
@@ -176,7 +194,7 @@ asf_close(asf_file_t *file)
for (i=0; i < ASF_MAX_STREAMS; i++) {
free(file->streams[i].properties);
free(file->streams[i].extended);
free(file->streams[i].extended_properties);
}
free(file);
+102 -99
View File
@@ -1,5 +1,5 @@
/* libasf - An Advanced Systems Format media file parser
* Copyright (C) 2006-2007 Juho Vähä-Herttua
* Copyright (C) 2006-2010 Juho Vähä-Herttua
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -19,9 +19,8 @@
#ifndef ASF_H
#define ASF_H
/* used int types for different platforms */
#if !defined(__MINGW_H) && defined(_WIN32)
#if defined(WIN32) && !defined(__MINGW_H)
typedef char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
@@ -35,13 +34,83 @@ typedef unsigned __int64 uint64_t;
#include <stdint.h>
#endif
struct asf_guid_s {
uint32_t v1;
uint32_t v2;
uint16_t v3;
uint8_t v4[8];
#if defined(WIN32) && defined(DLL_EXPORT)
# define LIBASF_API __declspec(dllexport)
#else
# define LIBASF_API
#endif
typedef enum {
/* fatal errors related to library function */
ASF_ERROR_INTERNAL = -100, /* incorrect input to API calls */
ASF_ERROR_OUTOFMEM = -101, /* some malloc inside program failed */
/* errors related to reading data from stream */
ASF_ERROR_NEEDS_BYTES = -200, /* not enough data from read */
ASF_ERROR_EOF = -201, /* end of file reached */
ASF_ERROR_IO = -202, /* error reading or writing to file */
/* errors related to file being corrupted */
ASF_ERROR_INVALID_LENGTH = -300, /* length value conflict in input data */
ASF_ERROR_INVALID_VALUE = -301, /* other value conflict in input data */
ASF_ERROR_INVALID_OBJECT = -302, /* ASF object missing or in wrong place */
ASF_ERROR_INVALID_OBJECT_SIZE = -303, /* invalid ASF object size (too small) */
/* errors related to seeking, usually non-fatal */
ASF_ERROR_SEEKABLE = -400, /* file not seekable */
ASF_ERROR_SEEK = -401 /* file is seekable but seeking failed */
} asf_error_t;
typedef enum {
ASF_STREAM_TYPE_NONE = 0x00,
ASF_STREAM_TYPE_AUDIO = 0x01,
ASF_STREAM_TYPE_VIDEO = 0x02,
ASF_STREAM_TYPE_COMMAND = 0x03,
ASF_STREAM_TYPE_UNKNOWN = 0xff
} asf_stream_type_t;
#define ASF_STREAM_FLAG_NONE 0x0000
#define ASF_STREAM_FLAG_AVAILABLE 0x0001
#define ASF_STREAM_FLAG_HIDDEN 0x0002
#define ASF_STREAM_FLAG_EXTENDED 0x0004
/* waveformatex fields specified in Microsoft documentation:
http://msdn2.microsoft.com/en-us/library/ms713497.aspx */
struct asf_waveformatex_s {
uint16_t wFormatTag;
uint16_t nChannels;
uint32_t nSamplesPerSec;
uint32_t nAvgBytesPerSec;
uint16_t nBlockAlign;
uint16_t wBitsPerSample;
uint16_t cbSize;
uint8_t *data;
};
typedef struct asf_guid_s asf_guid_t;
typedef struct asf_waveformatex_s asf_waveformatex_t;
#define ASF_BITMAPINFOHEADER_SIZE 40
/* bitmapinfoheader fields specified in Microsoft documentation:
http://msdn2.microsoft.com/en-us/library/ms532290.aspx */
struct asf_bitmapinfoheader_s {
uint32_t biSize;
uint32_t biWidth;
uint32_t biHeight;
uint16_t biPlanes;
uint16_t biBitCount;
uint32_t biCompression;
uint32_t biSizeImage;
uint32_t biXPelsPerMeter;
uint32_t biYPelsPerMeter;
uint32_t biClrUsed;
uint32_t biClrImportant;
uint8_t *data;
};
typedef struct asf_bitmapinfoheader_s asf_bitmapinfoheader_t;
struct asf_iostream_s {
/* read function, returns -1 on error, 0 on EOF and read bytes
@@ -102,6 +171,7 @@ struct asf_packet_s {
uint8_t *ec_data; /* error correction data array */
uint32_t length; /* length of this packet, usually constant per stream */
uint32_t sequence; /* sequence value reserved for future use, should be ignored */
uint32_t padding_length; /* length of the padding after the data in this packet */
uint32_t send_time; /* send time of this packet in milliseconds */
uint16_t duration; /* duration of this packet in milliseconds */
@@ -118,55 +188,7 @@ struct asf_packet_s {
};
typedef struct asf_packet_s asf_packet_t;
/* waveformatex fields specified in Microsoft documentation:
http://msdn2.microsoft.com/en-us/library/ms713497.aspx */
struct asf_waveformatex_s {
uint16_t wFormatTag;
uint16_t nChannels;
uint32_t nSamplesPerSec;
uint32_t nAvgBytesPerSec;
uint16_t nBlockAlign;
uint16_t wBitsPerSample;
uint16_t cbSize;
uint8_t *data;
};
typedef struct asf_waveformatex_s asf_waveformatex_t;
#define ASF_BITMAPINFOHEADER_SIZE 40
/* bitmapinfoheader fields specified in Microsoft documentation:
http://msdn2.microsoft.com/en-us/library/ms532290.aspx */
struct asf_bitmapinfoheader_s {
uint32_t biSize;
uint32_t biWidth;
uint32_t biHeight;
uint16_t biPlanes;
uint16_t biBitCount;
uint32_t biCompression;
uint32_t biSizeImage;
uint32_t biXPelsPerMeter;
uint32_t biYPelsPerMeter;
uint32_t biClrUsed;
uint32_t biClrImportant;
uint8_t *data;
};
typedef struct asf_bitmapinfoheader_s asf_bitmapinfoheader_t;
enum asf_stream_type_e {
ASF_STREAM_TYPE_NONE = 0x00,
ASF_STREAM_TYPE_AUDIO = 0x01,
ASF_STREAM_TYPE_VIDEO = 0x02,
ASF_STREAM_TYPE_COMMAND = 0x03,
ASF_STREAM_TYPE_UNKNOWN = 0xff
};
typedef enum asf_stream_type_e asf_stream_type_t;
#define ASF_STREAM_FLAG_NONE 0x0000
#define ASF_STREAM_FLAG_AVAILABLE 0x0001
#define ASF_STREAM_FLAG_HIDDEN 0x0002
#define ASF_STREAM_FLAG_EXTENDED 0x0004
struct asf_stream_extended_s {
struct asf_stream_extended_properties_s {
uint64_t start_time;
uint64_t end_time;
uint32_t data_bitrate;
@@ -183,7 +205,7 @@ struct asf_stream_extended_s {
uint16_t stream_name_count;
uint16_t num_payload_ext;
};
typedef struct asf_stream_extended_s asf_stream_extended_t;
typedef struct asf_stream_extended_properties_s asf_stream_extended_properties_t;
struct asf_stream_s {
asf_stream_type_t type; /* type of this current stream */
@@ -195,101 +217,82 @@ struct asf_stream_s {
/* pointer to extended properties of the stream if they specified
* only available if ASF_STREAM_FLAG_EXTENDED flag is set, otherwise NULL */
asf_stream_extended_t *extended;
asf_stream_extended_properties_t *extended_properties;
};
typedef struct asf_stream_s asf_stream_t;
typedef struct asf_file_s asf_file_t;
enum asf_error_e {
ASF_ERROR_INTERNAL = -1, /* incorrect input to API calls */
ASF_ERROR_OUTOFMEM = -2, /* some malloc inside program failed */
ASF_ERROR_EOF = -3, /* unexpected end of file */
ASF_ERROR_IO = -4, /* error reading or writing to file */
ASF_ERROR_INVALID_LENGTH = -5, /* length value conflict in input data */
ASF_ERROR_INVALID_VALUE = -6, /* other value conflict in input data */
ASF_ERROR_INVALID_OBJECT = -7, /* ASF object missing or in wrong place */
ASF_ERROR_OBJECT_SIZE = -8, /* invalid ASF object size (too small) */
ASF_ERROR_SEEKABLE = -9, /* file not seekable */
ASF_ERROR_SEEK = -10 /* file is seekable but seeking failed */
};
struct asf_object_s {
asf_guid_t guid;
uint64_t size;
uint8_t *data;
};
typedef struct asf_object_s asf_object_t;
/* initialize the library using file on a local filesystem */
asf_file_t *asf_open_file(const char *filename);
LIBASF_API asf_file_t *asf_open_file(const char *filename);
/* initialize the library using callbacks defined on a stream structure,
the stream structure can be freed after calling this function */
asf_file_t *asf_open_cb(asf_iostream_t *iostream);
LIBASF_API asf_file_t *asf_open_cb(asf_iostream_t *iostream);
/* close the library handle and free all allocated memory */
void asf_close(asf_file_t *file);
LIBASF_API void asf_close(asf_file_t *file);
/* initialize the library and read all header information of the ASF file */
int asf_init(asf_file_t *file);
LIBASF_API int asf_init(asf_file_t *file);
/* create a packet structure for reading data packets */
asf_packet_t *asf_packet_create();
LIBASF_API asf_packet_t *asf_packet_create();
/* free the packet structure allocated earlier, need to be called only once */
void asf_packet_destroy(asf_packet_t *packet);
LIBASF_API void asf_packet_destroy(asf_packet_t *packet);
/* get next packet from the stream to the specified packet structure */
int asf_get_packet(asf_file_t *file, asf_packet_t *packet);
LIBASF_API int asf_get_packet(asf_file_t *file, asf_packet_t *packet);
/* seek to the closest (key frame) packet specified by milliseconds position */
int64_t asf_seek_to_msec(asf_file_t *file, int64_t msec);
LIBASF_API int64_t asf_seek_to_msec(asf_file_t *file, int64_t msec);
/* get metadata information of the ASF file handle */
asf_metadata_t *asf_header_get_metadata(asf_file_t *file);
LIBASF_API asf_metadata_t *asf_header_get_metadata(asf_file_t *file);
/* free metadata structure received from the library */
void asf_metadata_destroy(asf_metadata_t *metadata);
LIBASF_API void asf_metadata_destroy(asf_metadata_t *metadata);
/* free all header information from the ASF file structure
* WARNING: after calling this function all asf_header_*
* functions will return NULL or failure!!! */
void asf_header_destroy(asf_file_t *file);
LIBASF_API void asf_header_destroy(asf_file_t *file);
/* calculate how many streams are available in current ASF file */
uint8_t asf_get_stream_count(asf_file_t *file);
LIBASF_API uint8_t asf_get_stream_count(asf_file_t *file);
/* get info of a stream, the resulting pointer and its contents should NOT be freed */
asf_stream_t *asf_get_stream(asf_file_t *file, uint8_t track);
LIBASF_API asf_stream_t *asf_get_stream(asf_file_t *file, uint8_t track);
/* return non-zero if the file is broadcasted, 0 otherwise */
int asf_is_broadcast(asf_file_t *file);
LIBASF_API int asf_is_broadcast(asf_file_t *file);
/* return non-zero if the file is seekable, 0 otherwise */
int asf_is_seekable(asf_file_t *file);
LIBASF_API int asf_is_seekable(asf_file_t *file);
/* get size of the ASF file in bytes */
uint64_t asf_get_file_size(asf_file_t *file);
LIBASF_API uint64_t asf_get_file_size(asf_file_t *file);
/* get creation date in 100-nanosecond units since Jan 1, 1601 GMT
this value should be ignored for broadcasts */
uint64_t asf_get_creation_date(asf_file_t *file);
LIBASF_API uint64_t asf_get_creation_date(asf_file_t *file);
/* get number of data packets available in this file
this value should be ignored for broadcasts */
uint64_t asf_get_data_packets(asf_file_t *file);
LIBASF_API uint64_t asf_get_data_packets(asf_file_t *file);
/* get play duration of the file in 100-nanosecond units,
this value should be ignored for broadcasts */
uint64_t asf_get_duration(asf_file_t *file);
LIBASF_API uint64_t asf_get_duration(asf_file_t *file);
/* maximum bitrate as bits per second in the entire file */
uint32_t asf_get_max_bitrate(asf_file_t *file);
LIBASF_API uint32_t asf_get_max_bitrate(asf_file_t *file);
#endif
@@ -1,5 +1,5 @@
/* libasf - An Advanced Systems Format media file parser
* Copyright (C) 2006-2007 Juho Vähä-Herttua
* Copyright (C) 2006-2010 Juho Vähä-Herttua
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -19,8 +19,28 @@
#ifndef ASFINT_H
#define ASFINT_H
#include <string.h>
#include "asf.h"
#include "guid.h"
#include "compat.h"
static INLINE void
GetGUID(const void *pointer, asf_guid_t *guid)
{
const uint8_t *data = pointer;
guid->v1 = GetDWLE(data);
guid->v2 = GetWLE(data + 4);
guid->v3 = GetWLE(data + 6);
memcpy(guid->v4, data + 8, 8);
}
#define GETLEN2b(bits) (((bits) == 0x03) ? 4 : bits)
#define GETVALUE2b(bits, data) \
(((bits) != 0x03) ? ((bits) != 0x02) ? ((bits) != 0x01) ? \
0 : *((uint8_t *)data) : GetWLE(data) : GetDWLE(data))
/* DO NOT MODIFY THE FIRST 3 VARIABLES, BECAUSE THEY ARE
* ALSO DEFINED IN asf.h HEADER AND WILL BREAK THINGS */
@@ -1,5 +1,5 @@
/* libasf - An Advanced Systems Format media file parser
* Copyright (C) 2006-2007 Juho Vähä-Herttua
* Copyright (C) 2006-2010 Juho Vähä-Herttua
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -17,71 +17,12 @@
*/
#include <string.h>
#include "asfint.h"
#include "byteio.h"
uint16_t
asf_byteio_getWLE(uint8_t *data)
{
uint16_t ret;
int i;
for (i=1, ret=0; i>=0; i--) {
ret <<= 8;
ret |= data[i];
}
return ret;
}
uint32_t
asf_byteio_getDWLE(uint8_t *data)
{
uint32_t ret;
int i;
for (i=3, ret=0; i>=0; i--) {
ret <<= 8;
ret |= data[i];
}
return ret;
}
uint64_t
asf_byteio_getQWLE(uint8_t *data)
{
uint64_t ret;
int i;
for (i=7, ret=0; i>=0; i--) {
ret <<= 8;
ret |= data[i];
}
return ret;
}
void
asf_byteio_getGUID(asf_guid_t *guid, uint8_t *data)
{
guid->v1 = asf_byteio_getDWLE(data);
guid->v2 = asf_byteio_getWLE(data + 4);
guid->v3 = asf_byteio_getWLE(data + 6);
memcpy(guid->v4, data + 8, 8);
}
void
asf_byteio_get_string(uint16_t *string, uint16_t strlen, uint8_t *data)
{
int i;
for (i=0; i<strlen; i++) {
string[i] = asf_byteio_getWLE(data + i*2);
}
}
int
asf_byteio_read(uint8_t *data, int size, asf_iostream_t *iostream)
asf_byteio_read(asf_iostream_t *iostream, uint8_t *data, int size)
{
int read = 0, tmp;
@@ -91,12 +32,14 @@ asf_byteio_read(uint8_t *data, int size, asf_iostream_t *iostream)
while ((tmp = iostream->read(iostream->opaque, data+read, size-read)) > 0) {
read += tmp;
if (read == size) {
return read;
}
}
/* FIXME: should return tmp if any bytes were read, but the
rest of the code needs to be fixed before that */
return (tmp == 0) ? ASF_ERROR_EOF : ASF_ERROR_IO;
}
@@ -1,5 +1,5 @@
/* libasf - An Advanced Systems Format media file parser
* Copyright (C) 2006-2007 Juho Vähä-Herttua
* Copyright (C) 2006-2010 Juho Vähä-Herttua
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -22,12 +22,6 @@
#include "asf.h"
#include "guid.h"
uint16_t asf_byteio_getWLE(uint8_t *data);
uint32_t asf_byteio_getDWLE(uint8_t *data);
uint64_t asf_byteio_getQWLE(uint8_t *data);
void asf_byteio_getGUID(asf_guid_t *guid, uint8_t *data);
void asf_byteio_get_string(uint16_t *string, uint16_t strlen, uint8_t *data);
int asf_byteio_read(uint8_t *data, int size, asf_iostream_t *iostream);
int asf_byteio_read(asf_iostream_t *iostream, uint8_t *data, int size);
#endif
@@ -0,0 +1,60 @@
/* libasf - An Advanced Systems Format media file parser
* Copyright (C) 2006-2010 Juho Vähä-Herttua
*
* 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
*/
#ifndef COMPAT_H
#define COMPAT_H
#ifdef __GNUC__
# define INLINE __inline__
#else
# define INLINE
#endif
static INLINE uint16_t
GetWLE(const void *pointer)
{
const uint8_t *data = pointer;
return ((uint16_t)data[1] << 8) |
((uint16_t)data[0]);
}
static INLINE uint32_t
GetDWLE(const void *pointer)
{
const uint8_t *data = pointer;
return ((uint32_t)data[3] << 24) |
((uint32_t)data[2] << 16) |
((uint32_t)data[1] << 8) |
((uint32_t)data[0]);
}
static INLINE uint64_t
GetQWLE(const void *pointer)
{
const uint8_t *data = pointer;
return ((uint64_t)data[7] << 56) |
((uint64_t)data[6] << 48) |
((uint64_t)data[5] << 40) |
((uint64_t)data[4] << 32) |
((uint64_t)data[3] << 24) |
((uint64_t)data[2] << 16) |
((uint64_t)data[1] << 8) |
((uint64_t)data[0]);
}
#endif
@@ -1,5 +1,5 @@
/* libasf - An Advanced Systems Format media file parser
* Copyright (C) 2006-2007 Juho Vähä-Herttua
* Copyright (C) 2006-2010 Juho Vähä-Herttua
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -19,22 +19,15 @@
#include <stdlib.h>
#include <string.h>
#include "asf.h"
#include "asfint.h"
#include "byteio.h"
#include "data.h"
#include "parse.h"
#include "debug.h"
#define GETLEN2b(bits) (((bits) == 0x03) ? 4 : bits)
#define GETVALUE2b(bits, data) \
(((bits) != 0x03) ? ((bits) != 0x02) ? ((bits) != 0x01) ? \
0 : *(data) : asf_byteio_getWLE(data) : asf_byteio_getDWLE(data))
static int
asf_data_read_packet_data(asf_packet_t *packet, uint8_t flags,
uint8_t *data, uint32_t len)
asf_data_read_packet_fields(asf_packet_t *packet, uint8_t flags,
uint8_t *data, uint32_t len)
{
uint8_t datalen;
@@ -48,21 +41,20 @@ asf_data_read_packet_data(asf_packet_t *packet, uint8_t flags,
packet->length = GETVALUE2b((flags >> 5) & 0x03, data);
data += GETLEN2b((flags >> 5) & 0x03);
/* sequence value should be never used anywhere */
GETVALUE2b((flags >> 1) & 0x03, data);
packet->sequence = GETVALUE2b((flags >> 1) & 0x03, data);
data += GETLEN2b((flags >> 1) & 0x03);
packet->padding_length = GETVALUE2b((flags >> 3) & 0x03, data);
data += GETLEN2b((flags >> 3) & 0x03);
packet->send_time = asf_byteio_getDWLE(data);
packet->send_time = GetDWLE(data);
data += 4;
packet->duration = asf_byteio_getWLE(data);
packet->duration = GetWLE(data);
data += 2;
return datalen;
}
static int
asf_data_read_payload_data(asf_payload_t *payload, uint8_t flags, uint8_t *data, int size)
asf_data_read_payload_fields(asf_payload_t *payload, uint8_t flags, uint8_t *data, int size)
{
uint8_t datalen;
@@ -88,24 +80,27 @@ static int
asf_data_read_payloads(asf_packet_t *packet,
uint64_t preroll,
uint8_t multiple,
uint8_t type,
uint8_t flags,
uint8_t *data,
uint32_t datalen)
{
asf_payload_t pl;
int i, tmp, skip;
uint32_t skip;
int i, tmp;
skip = 0, i = 0;
while (i < packet->payload_count) {
uint8_t pts_delta = 0;
int compressed = 0;
if (skip+1 > datalen) {
return ASF_ERROR_INVALID_LENGTH;
}
pl.stream_number = data[skip] & 0x7f;
pl.key_frame = !!(data[skip] & 0x80);
skip++;
tmp = asf_data_read_payload_data(&pl, flags, data + skip, datalen - skip);
tmp = asf_data_read_payload_fields(&pl, flags, data + skip, datalen - skip);
if (tmp < 0) {
return tmp;
}
@@ -119,9 +114,9 @@ asf_data_read_payloads(asf_packet_t *packet,
pl.replicated_data = data + skip;
skip += pl.replicated_length;
pl.pts = asf_byteio_getDWLE(pl.replicated_data + 4);
pl.pts = GetDWLE(pl.replicated_data + 4);
} else if (pl.replicated_length == 1) {
if (skip >= datalen) {
if (skip+1 > datalen) {
/* not enough data */
return ASF_ERROR_INVALID_LENGTH;
}
@@ -142,29 +137,26 @@ asf_data_read_payloads(asf_packet_t *packet,
}
/* substract preroll value from pts since it's counted in */
pl.pts -= preroll;
/* FIXME: check that pts is positive */
if (pl.pts > preroll) {
pl.pts -= preroll;
} else {
pl.pts = 0;
}
if (multiple) {
tmp = GETLEN2b(type);
if (tmp != 2) {
/* in multiple payloads datalen should be a word */
return ASF_ERROR_INVALID_VALUE;
}
if (skip + tmp > datalen) {
if (skip + 2 > datalen) {
/* not enough data */
return ASF_ERROR_INVALID_LENGTH;
}
pl.datalen = GETVALUE2b(type, data + skip);
skip += tmp;
pl.datalen = GetWLE(data + skip);
skip += 2;
} else {
pl.datalen = datalen - skip;
}
if (compressed) {
int payloads, start = skip, used = 0;
uint32_t start = skip, used = 0;
int payloads, idx;
/* count how many compressed payloads this payload includes */
for (payloads=0; used < pl.datalen; payloads++) {
@@ -190,20 +182,22 @@ asf_data_read_payloads(asf_packet_t *packet,
packet->payloads_size = packet->payload_count;
}
while (skip < start + used) {
for (idx = 0; idx < payloads; idx++) {
pl.datalen = data[skip];
skip++;
/* Set data correctly */
pl.data = data + skip;
skip += pl.datalen;
pl.pts += pts_delta;
/* Copy the final payload and update the PTS */
memcpy(&packet->payloads[i], &pl, sizeof(asf_payload_t));
packet->payloads[i].pts = pl.pts + idx * pts_delta;
i++;
debug_printf("payload(%d/%d) stream: %d, key frame: %d, object: %d, offset: %d, pts: %d, datalen: %d",
i, packet->payload_count, pl.stream_number, (int) pl.key_frame, pl.media_object_number,
pl.media_object_offset, pl.pts, pl.datalen);
pl.media_object_offset, pl.pts + idx * pts_delta, pl.datalen);
}
} else {
pl.data = data + skip;
@@ -249,7 +243,7 @@ asf_data_get_packet(asf_packet_t *packet, asf_file_t *file)
{
asf_iostream_t *iostream;
uint32_t read = 0;
int packet_flags, packet_property, payload_length_type;
int packet_flags, packet_property;
void *tmpptr;
int tmp;
@@ -268,9 +262,7 @@ asf_data_get_packet(asf_packet_t *packet, asf_file_t *file)
packet->data_size = file->packet_size;
}
tmp = asf_byteio_read(packet->data,
file->packet_size,
iostream);
tmp = asf_byteio_read(iostream, packet->data, file->packet_size);
if (tmp < 0) {
/* Error reading packet data */
return tmp;
@@ -298,6 +290,7 @@ asf_data_get_packet(asf_packet_t *packet, asf_file_t *file)
read += packet->ec_length;
} else {
packet->ec_length = 0;
packet->ec_data = NULL;
}
if (read+2 > file->packet_size) {
@@ -306,10 +299,9 @@ asf_data_get_packet(asf_packet_t *packet, asf_file_t *file)
packet_flags = packet->data[read++];
packet_property = packet->data[read++];
tmp = asf_data_read_packet_data(packet,
packet_flags,
&packet->data[read],
file->packet_size - read);
tmp = asf_data_read_packet_fields(packet, packet_flags,
packet->data + read,
file->packet_size - read);
if (tmp < 0) {
return tmp;
}
@@ -318,13 +310,13 @@ asf_data_get_packet(asf_packet_t *packet, asf_file_t *file)
/* this is really idiotic, packet length can (and often will) be
* undefined and we just have to use the header packet size as the size
* value */
if (!((packet_flags >> 5) & 0x03)) {
if (((packet_flags >> 5) & 0x03) == 0) {
packet->length = file->packet_size;
}
/* this is also really idiotic, if packet length is smaller than packet
* size, we need to manually add the additional bytes into padding length
*/
* because the padding bytes only count up to packet length value */
if (packet->length < file->packet_size) {
packet->padding_length += file->packet_size - packet->length;
packet->length = file->packet_size;
@@ -337,6 +329,8 @@ asf_data_get_packet(asf_packet_t *packet, asf_file_t *file)
/* check if we have multiple payloads */
if (packet_flags & 0x01) {
int payload_length_type;
if (read+1 > packet->length) {
return ASF_ERROR_INVALID_LENGTH;
}
@@ -344,11 +338,19 @@ asf_data_get_packet(asf_packet_t *packet, asf_file_t *file)
packet->payload_count = tmp & 0x3f;
payload_length_type = (tmp >> 6) & 0x03;
if (packet->payload_count == 0) {
/* there should always be at least one payload */
return ASF_ERROR_INVALID_VALUE;
}
if (payload_length_type != 0x02) {
/* in multiple payloads datalen should always be a word */
return ASF_ERROR_INVALID_VALUE;
}
} else {
packet->payload_count = 1;
payload_length_type = 0x02; /* not used */
}
packet->payload_data_len = packet->length - read;
if (packet->payload_count > packet->payloads_size) {
@@ -363,11 +365,10 @@ asf_data_get_packet(asf_packet_t *packet, asf_file_t *file)
packet->payload_data = &packet->data[read];
read += packet->payload_data_len;
/* The return value will be consumed bytes, not including the padding */
tmp = asf_data_read_payloads(packet, file->preroll, packet_flags & 0x01,
payload_length_type, packet_property,
packet->payload_data,
packet_property, packet->payload_data,
packet->payload_data_len - packet->padding_length);
if (tmp < 0) {
return tmp;
@@ -1,5 +1,5 @@
/* libasf - An Advanced Systems Format media file parser
* Copyright (C) 2006-2007 Juho Vähä-Herttua
* Copyright (C) 2006-2010 Juho Vähä-Herttua
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -1,5 +1,5 @@
/* libasf - An Advanced Systems Format media file parser
* Copyright (C) 2006-2007 Juho Vähä-Herttua
* Copyright (C) 2006-2010 Juho Vähä-Herttua
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -22,23 +22,24 @@
#include <stdio.h>
#include <stdarg.h>
#ifdef __GNUC__
# define INLINE static __inline__
#else
# define INLINE
#endif
#include "asfint.h"
INLINE void
#if defined(WIN32) && defined(DEBUG)
# define debug_printf printf
#else
static void
debug_printf(char *fmt, ...)
{
#ifdef DEBUG
# ifdef DEBUG
va_list argp;
va_start(argp, fmt);
vfprintf(stderr, fmt, argp);
va_end(argp);
fprintf(stderr, "\n");
#endif
# endif
}
#endif
#endif
@@ -1,63 +0,0 @@
/* libasf - An Advanced Systems Format media file parser
* Copyright (C) 2006-2007 Juho Vähä-Herttua
*
* 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 <stdio.h>
#include "asf.h"
/**
* Implement callback functions for basic file I/O operations,
* so that users wouldn't need to reimplement them.
*/
int
asf_fileio_read_cb(FILE *stream, void *buffer, int size)
{
int ret;
ret = fread(buffer, 1, size, stream);
if (!ret && !feof(stream))
ret = -1;
return ret;
}
int
asf_fileio_write_cb(FILE *stream, void *buffer, int size)
{
int ret;
ret = fwrite(buffer, 1, size, stream);
if (!ret && !feof(stream))
ret = -1;
return ret;
}
int64_t
asf_fileio_seek_cb(FILE *stream, int64_t offset)
{
int ret;
ret = fseek(stream, offset, SEEK_SET);
if (ret < 0)
return -1;
return offset;
}
@@ -1,28 +0,0 @@
/* libasf - An Advanced Systems Format media file parser
* Copyright (C) 2006-2007 Juho Vähä-Herttua
*
* 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
*/
#ifndef FILEIO_H
#define FILEIO_H
#include "asf.h"
int asf_fileio_read_cb(void *stream, void *buffer, int size);
int asf_fileio_write_cb(void *stream, void *buffer, int size);
int64_t asf_fileio_seek_cb(void *stream, int64_t offset);
#endif
@@ -1,5 +1,5 @@
/* libasf - An Advanced Systems Format media file parser
* Copyright (C) 2006-2007 Juho Vähä-Herttua
* Copyright (C) 2006-2010 Juho Vähä-Herttua
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -103,7 +103,7 @@ static const asf_guid_t asf_guid_stream_type_extended_audio =
int
asf_guid_match(const asf_guid_t *guid1, const asf_guid_t *guid2)
asf_guid_equals(const asf_guid_t *guid1, const asf_guid_t *guid2)
{
if((guid1->v1 != guid2->v1) ||
(guid1->v2 != guid2->v2) ||
@@ -120,41 +120,41 @@ asf_guid_get_object_type(const asf_guid_t *guid)
{
guid_type_t ret = GUID_UNKNOWN;
if (asf_guid_match(guid, &asf_guid_header))
if (asf_guid_equals(guid, &asf_guid_header))
ret = GUID_HEADER;
else if (asf_guid_match(guid, &asf_guid_data))
else if (asf_guid_equals(guid, &asf_guid_data))
ret = GUID_DATA;
else if (asf_guid_match(guid, &asf_guid_index))
else if (asf_guid_equals(guid, &asf_guid_index))
ret = GUID_INDEX;
else if (asf_guid_match(guid, &asf_guid_file_properties))
else if (asf_guid_equals(guid, &asf_guid_file_properties))
ret = GUID_FILE_PROPERTIES;
else if (asf_guid_match(guid, &asf_guid_stream_properties))
else if (asf_guid_equals(guid, &asf_guid_stream_properties))
ret = GUID_STREAM_PROPERTIES;
else if (asf_guid_match(guid, &asf_guid_content_description))
else if (asf_guid_equals(guid, &asf_guid_content_description))
ret = GUID_CONTENT_DESCRIPTION;
else if (asf_guid_match(guid, &asf_guid_header_extension))
else if (asf_guid_equals(guid, &asf_guid_header_extension))
ret = GUID_HEADER_EXTENSION;
else if (asf_guid_match(guid, &asf_guid_marker))
else if (asf_guid_equals(guid, &asf_guid_marker))
ret = GUID_MARKER;
else if (asf_guid_match(guid, &asf_guid_codec_list))
else if (asf_guid_equals(guid, &asf_guid_codec_list))
ret = GUID_CODEC_LIST;
else if (asf_guid_match(guid, &asf_guid_stream_bitrate_properties))
else if (asf_guid_equals(guid, &asf_guid_stream_bitrate_properties))
ret = GUID_STREAM_BITRATE_PROPERTIES;
else if (asf_guid_match(guid, &asf_guid_padding))
else if (asf_guid_equals(guid, &asf_guid_padding))
ret = GUID_PADDING;
else if (asf_guid_match(guid, &asf_guid_extended_content_description))
else if (asf_guid_equals(guid, &asf_guid_extended_content_description))
ret = GUID_EXTENDED_CONTENT_DESCRIPTION;
else if (asf_guid_match(guid, &asf_guid_metadata))
else if (asf_guid_equals(guid, &asf_guid_metadata))
ret = GUID_METADATA;
else if (asf_guid_match(guid, &asf_guid_language_list))
else if (asf_guid_equals(guid, &asf_guid_language_list))
ret = GUID_LANGUAGE_LIST;
else if (asf_guid_match(guid, &asf_guid_extended_stream_properties))
else if (asf_guid_equals(guid, &asf_guid_extended_stream_properties))
ret = GUID_EXTENDED_STREAM_PROPERTIES;
else if (asf_guid_match(guid, &asf_guid_advanced_mutual_exclusion))
else if (asf_guid_equals(guid, &asf_guid_advanced_mutual_exclusion))
ret = GUID_ADVANCED_MUTUAL_EXCLUSION;
else if (asf_guid_match(guid, &asf_guid_stream_prioritization))
else if (asf_guid_equals(guid, &asf_guid_stream_prioritization))
ret = GUID_STREAM_PRIORITIZATION;
return ret;
@@ -165,15 +165,15 @@ asf_guid_get_stream_type(const asf_guid_t *guid)
{
guid_type_t ret = GUID_UNKNOWN;
if (asf_guid_match(guid, &asf_guid_stream_type_audio))
if (asf_guid_equals(guid, &asf_guid_stream_type_audio))
ret = GUID_STREAM_TYPE_AUDIO;
else if (asf_guid_match(guid, &asf_guid_stream_type_video))
else if (asf_guid_equals(guid, &asf_guid_stream_type_video))
ret = GUID_STREAM_TYPE_VIDEO;
else if (asf_guid_match(guid, &asf_guid_stream_type_command))
else if (asf_guid_equals(guid, &asf_guid_stream_type_command))
ret = GUID_STREAM_TYPE_COMMAND;
else if (asf_guid_match(guid, &asf_guid_stream_type_extended))
else if (asf_guid_equals(guid, &asf_guid_stream_type_extended))
ret = GUID_STREAM_TYPE_EXTENDED;
else if (asf_guid_match(guid, &asf_guid_stream_type_extended_audio))
else if (asf_guid_equals(guid, &asf_guid_stream_type_extended_audio))
ret = GUID_STREAM_TYPE_EXTENDED_AUDIO;
return ret;
@@ -1,5 +1,5 @@
/* libasf - An Advanced Systems Format media file parser
* Copyright (C) 2006-2007 Juho Vähä-Herttua
* Copyright (C) 2006-2010 Juho Vähä-Herttua
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -21,7 +21,15 @@
#include "asf.h"
enum guid_type_e {
struct asf_guid_s {
uint32_t v1;
uint32_t v2;
uint16_t v3;
uint8_t v4[8];
};
typedef struct asf_guid_s asf_guid_t;
typedef enum {
GUID_UNKNOWN,
GUID_HEADER,
@@ -49,11 +57,10 @@ enum guid_type_e {
GUID_STREAM_TYPE_COMMAND,
GUID_STREAM_TYPE_EXTENDED,
GUID_STREAM_TYPE_EXTENDED_AUDIO
};
typedef enum guid_type_e guid_type_t;
} guid_type_t;
int asf_guid_match(const asf_guid_t *guid1, const asf_guid_t *guid2);
int asf_guid_equals(const asf_guid_t *guid1, const asf_guid_t *guid2);
guid_type_t asf_guid_get_object_type(const asf_guid_t *guid);
guid_type_t asf_guid_get_stream_type(const asf_guid_t *guid);
guid_type_t asf_guid_get_type(const asf_guid_t *guid);
@@ -1,5 +1,5 @@
/* libasf - An Advanced Systems Format media file parser
* Copyright (C) 2006-2007 Juho Vähä-Herttua
* Copyright (C) 2006-2010 Juho Vähä-Herttua
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -20,7 +20,6 @@
#include <stdlib.h>
#include <string.h>
#include "asf.h"
#include "asfint.h"
#include "utf.h"
#include "header.h"
@@ -68,10 +67,10 @@ asf_parse_header_stream_properties(asf_stream_t *stream,
return ASF_ERROR_INVALID_LENGTH;
}
asf_byteio_getGUID(&guid, objdata);
GetGUID(objdata, &guid);
type = asf_guid_get_stream_type(&guid);
datalen = asf_byteio_getDWLE(objdata + 40);
datalen = GetDWLE(objdata + 40);
if (datalen > objsize - 78) {
return ASF_ERROR_INVALID_LENGTH;
}
@@ -87,7 +86,7 @@ asf_parse_header_stream_properties(asf_stream_t *stream,
datalen -= 64;
/* update the stream type with correct one */
asf_byteio_getGUID(&guid, objdata);
GetGUID(objdata, &guid);
type = asf_guid_get_stream_type(&guid);
}
@@ -102,7 +101,7 @@ asf_parse_header_stream_properties(asf_stream_t *stream,
if (datalen < 18) {
return ASF_ERROR_INVALID_LENGTH;
}
if (asf_byteio_getWLE(data + 16) > datalen - 16) {
if (GetWLE(data + 16) > datalen - 16) {
return ASF_ERROR_INVALID_LENGTH;
}
@@ -113,13 +112,13 @@ asf_parse_header_stream_properties(asf_stream_t *stream,
stream->flags |= ASF_STREAM_FLAG_AVAILABLE;
wfx = stream->properties;
wfx->wFormatTag = asf_byteio_getWLE(data);
wfx->nChannels = asf_byteio_getWLE(data + 2);
wfx->nSamplesPerSec = asf_byteio_getDWLE(data + 4);
wfx->nAvgBytesPerSec = asf_byteio_getDWLE(data + 8);
wfx->nBlockAlign = asf_byteio_getWLE(data + 12);
wfx->wBitsPerSample = asf_byteio_getWLE(data + 14);
wfx->cbSize = asf_byteio_getWLE(data + 16);
wfx->wFormatTag = GetWLE(data);
wfx->nChannels = GetWLE(data + 2);
wfx->nSamplesPerSec = GetDWLE(data + 4);
wfx->nAvgBytesPerSec = GetDWLE(data + 8);
wfx->nBlockAlign = GetWLE(data + 12);
wfx->wBitsPerSample = GetWLE(data + 14);
wfx->cbSize = GetWLE(data + 16);
wfx->data = data + 18;
if (wfx->cbSize > datalen - 18) {
@@ -140,19 +139,19 @@ asf_parse_header_stream_properties(asf_stream_t *stream,
return ASF_ERROR_INVALID_LENGTH;
}
width = asf_byteio_getDWLE(data);
height = asf_byteio_getDWLE(data + 4);
width = GetDWLE(data);
height = GetDWLE(data + 4);
flags = data[8];
data_size = asf_byteio_getWLE(data + 9);
data_size = GetWLE(data + 9);
data += 11;
datalen -= 11;
if (asf_byteio_getDWLE(data) != datalen) {
if (GetDWLE(data) != datalen) {
return ASF_ERROR_INVALID_LENGTH;
}
if (width != asf_byteio_getDWLE(data + 4) ||
height != asf_byteio_getDWLE(data + 8) ||
if (width != GetDWLE(data + 4) ||
height != GetDWLE(data + 8) ||
flags != 2) {
return ASF_ERROR_INVALID_VALUE;
}
@@ -164,17 +163,17 @@ asf_parse_header_stream_properties(asf_stream_t *stream,
stream->flags |= ASF_STREAM_FLAG_AVAILABLE;
bmih = stream->properties;
bmih->biSize = asf_byteio_getDWLE(data);
bmih->biWidth = asf_byteio_getDWLE(data + 4);
bmih->biHeight = asf_byteio_getDWLE(data + 8);
bmih->biPlanes = asf_byteio_getDWLE(data + 12);
bmih->biBitCount = asf_byteio_getDWLE(data + 14);
bmih->biCompression = asf_byteio_getDWLE(data + 16);
bmih->biSizeImage = asf_byteio_getDWLE(data + 20);
bmih->biXPelsPerMeter = asf_byteio_getDWLE(data + 24);
bmih->biYPelsPerMeter = asf_byteio_getDWLE(data + 28);
bmih->biClrUsed = asf_byteio_getDWLE(data + 32);
bmih->biClrImportant = asf_byteio_getDWLE(data + 36);
bmih->biSize = GetDWLE(data);
bmih->biWidth = GetDWLE(data + 4);
bmih->biHeight = GetDWLE(data + 8);
bmih->biPlanes = GetDWLE(data + 12);
bmih->biBitCount = GetDWLE(data + 14);
bmih->biCompression = GetDWLE(data + 16);
bmih->biSizeImage = GetDWLE(data + 20);
bmih->biXPelsPerMeter = GetDWLE(data + 24);
bmih->biYPelsPerMeter = GetDWLE(data + 28);
bmih->biClrUsed = GetDWLE(data + 32);
bmih->biClrImportant = GetDWLE(data + 36);
bmih->data = data + 40;
if (bmih->biSize > datalen) {
@@ -200,27 +199,27 @@ asf_parse_header_extended_stream_properties(asf_stream_t *stream,
uint8_t *objdata,
uint32_t objsize)
{
asf_stream_extended_t ext;
asf_stream_extended_properties_t ext;
uint32_t datalen;
uint8_t *data;
uint16_t flags;
int i;
ext.start_time = asf_byteio_getQWLE(objdata);
ext.end_time = asf_byteio_getQWLE(objdata + 8);
ext.data_bitrate = asf_byteio_getDWLE(objdata + 16);
ext.buffer_size = asf_byteio_getDWLE(objdata + 20);
ext.initial_buf_fullness = asf_byteio_getDWLE(objdata + 24);
ext.data_bitrate2 = asf_byteio_getDWLE(objdata + 28);
ext.buffer_size2 = asf_byteio_getDWLE(objdata + 32);
ext.initial_buf_fullness2 = asf_byteio_getDWLE(objdata + 36);
ext.max_obj_size = asf_byteio_getDWLE(objdata + 40);
ext.flags = asf_byteio_getDWLE(objdata + 44);
ext.stream_num = asf_byteio_getWLE(objdata + 48);
ext.lang_idx = asf_byteio_getWLE(objdata + 50);
ext.avg_time_per_frame = asf_byteio_getQWLE(objdata + 52);
ext.stream_name_count = asf_byteio_getWLE(objdata + 60);
ext.num_payload_ext = asf_byteio_getWLE(objdata + 62);
ext.start_time = GetQWLE(objdata);
ext.end_time = GetQWLE(objdata + 8);
ext.data_bitrate = GetDWLE(objdata + 16);
ext.buffer_size = GetDWLE(objdata + 20);
ext.initial_buf_fullness = GetDWLE(objdata + 24);
ext.data_bitrate2 = GetDWLE(objdata + 28);
ext.buffer_size2 = GetDWLE(objdata + 32);
ext.initial_buf_fullness2 = GetDWLE(objdata + 36);
ext.max_obj_size = GetDWLE(objdata + 40);
ext.flags = GetDWLE(objdata + 44);
ext.stream_num = GetWLE(objdata + 48);
ext.lang_idx = GetWLE(objdata + 50);
ext.avg_time_per_frame = GetQWLE(objdata + 52);
ext.stream_name_count = GetWLE(objdata + 60);
ext.num_payload_ext = GetWLE(objdata + 62);
datalen = objsize - 88;
data = objdata + 64;
@@ -233,7 +232,7 @@ asf_parse_header_extended_stream_properties(asf_stream_t *stream,
return ASF_ERROR_INVALID_VALUE;
}
strlen = asf_byteio_getWLE(data + 2);
strlen = GetWLE(data + 2);
if (strlen > datalen) {
return ASF_ERROR_INVALID_LENGTH;
}
@@ -251,7 +250,7 @@ asf_parse_header_extended_stream_properties(asf_stream_t *stream,
return ASF_ERROR_INVALID_VALUE;
}
extsyslen = asf_byteio_getDWLE(data + 18);
extsyslen = GetDWLE(data + 18);
if (extsyslen > datalen) {
return ASF_ERROR_INVALID_LENGTH;
}
@@ -268,19 +267,19 @@ asf_parse_header_extended_stream_properties(asf_stream_t *stream,
/* this is almost same as in stream properties handler */
if (datalen < 78) {
return ASF_ERROR_OBJECT_SIZE;
return ASF_ERROR_INVALID_OBJECT_SIZE;
}
/* check that we really have a stream properties object */
asf_byteio_getGUID(&guid, data);
GetGUID(data, &guid);
if (asf_guid_get_type(&guid) != GUID_STREAM_PROPERTIES) {
return ASF_ERROR_INVALID_OBJECT;
}
if (asf_byteio_getQWLE(data + 16) != datalen) {
return ASF_ERROR_OBJECT_SIZE;
if (GetQWLE(data + 16) != datalen) {
return ASF_ERROR_INVALID_OBJECT_SIZE;
}
flags = asf_byteio_getWLE(data + 72);
flags = GetWLE(data + 72);
if ((flags & 0x7f) != ext.stream_num || stream->type) {
/* only one stream object per stream allowed and
@@ -300,12 +299,12 @@ asf_parse_header_extended_stream_properties(asf_stream_t *stream,
}
}
stream->extended = malloc(sizeof(asf_stream_extended_t));
if (!stream->extended) {
stream->extended_properties = malloc(sizeof(asf_stream_extended_properties_t));
if (!stream->extended_properties) {
return ASF_ERROR_OUTOFMEM;
}
stream->flags |= ASF_STREAM_FLAG_EXTENDED;
memcpy(stream->extended, &ext, sizeof(ext));
memcpy(stream->extended_properties, &ext, sizeof(ext));
return 0;
}
@@ -333,7 +332,7 @@ asf_parse_header_validate(asf_file_t *file, asf_object_header_t *header)
{
uint32_t max_packet_size;
if (size < 104)
return ASF_ERROR_OBJECT_SIZE;
return ASF_ERROR_INVALID_OBJECT_SIZE;
if (fileprop) {
/* multiple file properties objects not allowed */
@@ -341,18 +340,18 @@ asf_parse_header_validate(asf_file_t *file, asf_object_header_t *header)
}
fileprop = 1;
asf_byteio_getGUID(&file->file_id, current->data);
file->file_size = asf_byteio_getQWLE(current->data + 16);
file->creation_date = asf_byteio_getQWLE(current->data + 24);
file->data_packets_count = asf_byteio_getQWLE(current->data + 32);
file->play_duration = asf_byteio_getQWLE(current->data + 40);
file->send_duration = asf_byteio_getQWLE(current->data + 48);
file->preroll = asf_byteio_getQWLE(current->data + 56);
file->flags = asf_byteio_getDWLE(current->data + 64);
file->packet_size = asf_byteio_getDWLE(current->data + 68);
file->max_bitrate = asf_byteio_getQWLE(current->data + 76);
GetGUID(current->data, &file->file_id);
file->file_size = GetQWLE(current->data + 16);
file->creation_date = GetQWLE(current->data + 24);
file->data_packets_count = GetQWLE(current->data + 32);
file->play_duration = GetQWLE(current->data + 40);
file->send_duration = GetQWLE(current->data + 48);
file->preroll = GetQWLE(current->data + 56);
file->flags = GetDWLE(current->data + 64);
file->packet_size = GetDWLE(current->data + 68);
file->max_bitrate = GetQWLE(current->data + 76);
max_packet_size = asf_byteio_getDWLE(current->data + 72);
max_packet_size = GetDWLE(current->data + 72);
if (file->packet_size != max_packet_size) {
/* in ASF file minimum packet size and maximum
* packet size have to be same apparently...
@@ -368,10 +367,10 @@ asf_parse_header_validate(asf_file_t *file, asf_object_header_t *header)
int ret;
if (size < 78)
return ASF_ERROR_OBJECT_SIZE;
return ASF_ERROR_INVALID_OBJECT_SIZE;
streamprop = 1;
flags = asf_byteio_getWLE(current->data + 48);
flags = GetWLE(current->data + 48);
stream = &file->streams[flags & 0x7f];
if (stream->type) {
@@ -393,13 +392,13 @@ asf_parse_header_validate(asf_file_t *file, asf_object_header_t *header)
uint32_t stringlen = 0;
if (size < 34)
return ASF_ERROR_OBJECT_SIZE;
return ASF_ERROR_INVALID_OBJECT_SIZE;
stringlen += asf_byteio_getWLE(current->data);
stringlen += asf_byteio_getWLE(current->data + 2);
stringlen += asf_byteio_getWLE(current->data + 4);
stringlen += asf_byteio_getWLE(current->data + 6);
stringlen += asf_byteio_getWLE(current->data + 8);
stringlen += GetWLE(current->data);
stringlen += GetWLE(current->data + 2);
stringlen += GetWLE(current->data + 4);
stringlen += GetWLE(current->data + 6);
stringlen += GetWLE(current->data + 8);
if (size < stringlen + 34) {
/* invalid string length values */
@@ -411,17 +410,17 @@ asf_parse_header_validate(asf_file_t *file, asf_object_header_t *header)
break;
case GUID_CODEC_LIST:
if (size < 44)
return ASF_ERROR_OBJECT_SIZE;
return ASF_ERROR_INVALID_OBJECT_SIZE;
break;
case GUID_STREAM_BITRATE_PROPERTIES:
if (size < 26)
return ASF_ERROR_OBJECT_SIZE;
return ASF_ERROR_INVALID_OBJECT_SIZE;
break;
case GUID_PADDING:
break;
case GUID_EXTENDED_CONTENT_DESCRIPTION:
if (size < 26)
return ASF_ERROR_OBJECT_SIZE;
return ASF_ERROR_INVALID_OBJECT_SIZE;
break;
case GUID_UNKNOWN:
/* unknown guid type */
@@ -443,11 +442,11 @@ asf_parse_header_validate(asf_file_t *file, asf_object_header_t *header)
switch (current->type) {
case GUID_METADATA:
if (size < 26)
return ASF_ERROR_OBJECT_SIZE;
return ASF_ERROR_INVALID_OBJECT_SIZE;
break;
case GUID_LANGUAGE_LIST:
if (size < 26)
return ASF_ERROR_OBJECT_SIZE;
return ASF_ERROR_INVALID_OBJECT_SIZE;
break;
case GUID_EXTENDED_STREAM_PROPERTIES:
{
@@ -456,9 +455,9 @@ asf_parse_header_validate(asf_file_t *file, asf_object_header_t *header)
int ret;
if (size < 88)
return ASF_ERROR_OBJECT_SIZE;
return ASF_ERROR_INVALID_OBJECT_SIZE;
stream_num = asf_byteio_getWLE(current->data + 48);
stream_num = GetWLE(current->data + 48);
stream = &file->streams[stream_num];
ret = asf_parse_header_extended_stream_properties(stream,
@@ -472,11 +471,11 @@ asf_parse_header_validate(asf_file_t *file, asf_object_header_t *header)
}
case GUID_ADVANCED_MUTUAL_EXCLUSION:
if (size < 42)
return ASF_ERROR_OBJECT_SIZE;
return ASF_ERROR_INVALID_OBJECT_SIZE;
break;
case GUID_STREAM_PRIORITIZATION:
if (size < 26)
return ASF_ERROR_OBJECT_SIZE;
return ASF_ERROR_INVALID_OBJECT_SIZE;
break;
case GUID_UNKNOWN:
/* unknown guid type */
@@ -556,7 +555,7 @@ asf_header_metadata(asf_object_header_t *header)
/* The validity of the object is already checked so we can assume
* there's always enough data to read and there are no overflows */
for (i=0; i<5; i++) {
strlen = asf_byteio_getWLE(current->data + i*2);
strlen = GetWLE(current->data + i*2);
if (!strlen)
continue;
@@ -590,7 +589,7 @@ asf_header_metadata(asf_object_header_t *header)
if (current) {
int i, j, position;
ret->extended_count = asf_byteio_getWLE(current->data);
ret->extended_count = GetWLE(current->data);
ret->extended = calloc(ret->extended_count, sizeof(asf_metadata_entry_t));
if (!ret->extended) {
/* Clean up the already allocated parts and return */
@@ -608,16 +607,16 @@ asf_header_metadata(asf_object_header_t *header)
for (i=0; i<ret->extended_count; i++) {
uint16_t length, type;
length = asf_byteio_getWLE(current->data + position);
length = GetWLE(current->data + position);
position += 2;
ret->extended[i].key = asf_utf8_from_utf16le(current->data + position, length);
position += length;
type = asf_byteio_getWLE(current->data + position);
type = GetWLE(current->data + position);
position += 2;
length = asf_byteio_getWLE(current->data + position);
length = GetWLE(current->data + position);
position += 2;
switch (type) {
@@ -645,19 +644,19 @@ asf_header_metadata(asf_object_header_t *header)
/* type of the value is a signed 32-bit integer */
ret->extended[i].value = malloc(11 * sizeof(char));
sprintf(ret->extended[i].value, "%u",
asf_byteio_getDWLE(current->data + position));
GetDWLE(current->data + position));
break;
case 4:
/* FIXME: This doesn't print whole 64-bit integer */
ret->extended[i].value = malloc(21 * sizeof(char));
sprintf(ret->extended[i].value, "%u",
(uint32_t) asf_byteio_getQWLE(current->data + position));
(uint32_t) GetQWLE(current->data + position));
break;
case 5:
/* type of the value is a signed 16-bit integer */
ret->extended[i].value = malloc(6 * sizeof(char));
sprintf(ret->extended[i].value, "%u",
asf_byteio_getWLE(current->data + position));
GetWLE(current->data + position));
break;
default:
/* Unknown value type... */
@@ -1,5 +1,5 @@
/* libasf - An Advanced Systems Format media file parser
* Copyright (C) 2006-2007 Juho Vähä-Herttua
* Copyright (C) 2006-2010 Juho Vähä-Herttua
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -1,5 +1,5 @@
/* libasf - An Advanced Systems Format media file parser
* Copyright (C) 2006-2007 Juho Vähä-Herttua
* Copyright (C) 2006-2010 Juho Vähä-Herttua
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -22,7 +22,6 @@
#include "asf.h"
#include "asfint.h"
#include "byteio.h"
#include "utf.h"
#include "header.h"
#include "guid.h"
#include "debug.h"
@@ -36,9 +35,9 @@
static void
asf_parse_read_object(asfint_object_t *obj, uint8_t *data)
{
asf_byteio_getGUID(&obj->guid, data);
GetGUID(data, &obj->guid);
obj->type = asf_guid_get_type(&obj->guid);
obj->size = asf_byteio_getQWLE(data + 16);
obj->size = GetQWLE(data + 16);
obj->full_data = data;
obj->datalen = 0;
obj->data = NULL;
@@ -66,13 +65,13 @@ asf_parse_headerext(asf_object_headerext_t *header, uint8_t *buf, uint64_t bufle
if (header->size < 46) {
/* invalide size for headerext */
return ASF_ERROR_OBJECT_SIZE;
return ASF_ERROR_INVALID_OBJECT_SIZE;
}
/* Read reserved and datalen fields from the buffer */
asf_byteio_getGUID(&header->reserved1, buf + 24);
header->reserved2 = asf_byteio_getWLE(buf + 40);
header->datalen = asf_byteio_getDWLE(buf + 42);
GetGUID(buf + 24, &header->reserved1);
header->reserved2 = GetWLE(buf + 40);
header->datalen = GetDWLE(buf + 42);
if (header->datalen != header->size - 46) {
/* invalid header extension data length value */
@@ -149,7 +148,7 @@ asf_parse_header(asf_file_t *file)
/* object minimum is 24 bytes and header needs to have
* the subobject count field and two reserved fields */
tmp = asf_byteio_read(hdata, 30, iostream);
tmp = asf_byteio_read(iostream, hdata, 30);
if (tmp < 0) {
/* not enough data to read the header object */
return tmp;
@@ -165,11 +164,11 @@ asf_parse_header(asf_file_t *file)
asf_parse_read_object((asfint_object_t *) header, hdata);
if (header->size < 30) {
/* invalid size for header object */
return ASF_ERROR_OBJECT_SIZE;
return ASF_ERROR_INVALID_OBJECT_SIZE;
}
/* read header object specific compulsory fields */
header->subobjects = asf_byteio_getDWLE(hdata + 24);
header->subobjects = GetDWLE(hdata + 24);
header->reserved1 = hdata[28];
header->reserved2 = hdata[29];
@@ -185,7 +184,7 @@ asf_parse_header(asf_file_t *file)
return ASF_ERROR_OUTOFMEM;
}
tmp = asf_byteio_read(header->data, header->datalen, iostream);
tmp = asf_byteio_read(iostream, header->data, header->datalen);
if (tmp < 0) {
return tmp;
}
@@ -300,7 +299,7 @@ asf_parse_data(asf_file_t *file)
/* object minimum is 24 bytes and data object needs to have
* 26 additional bytes for its internal fields */
tmp = asf_byteio_read(ddata, 50, iostream);
tmp = asf_byteio_read(iostream, ddata, 50);
if (tmp < 0) {
return tmp;
}
@@ -315,22 +314,22 @@ asf_parse_data(asf_file_t *file)
asf_parse_read_object((asfint_object_t *) data, ddata);
if (data->size < 50) {
/* invalid size for data object */
return ASF_ERROR_OBJECT_SIZE;
return ASF_ERROR_INVALID_OBJECT_SIZE;
}
/* read data object specific compulsory fields */
asf_byteio_getGUID(&data->file_id, ddata + 24);
data->total_data_packets = asf_byteio_getQWLE(ddata + 40);
data->reserved = asf_byteio_getWLE(ddata + 48);
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_match(&data->file_id, &file->file_id)) {
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 iostream) and
/* 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) {
@@ -361,7 +360,7 @@ asf_parse_index(asf_file_t *file)
iostream = &file->iostream;
/* read the raw data of an index header */
tmp = asf_byteio_read(idata, 56, iostream);
tmp = asf_byteio_read(iostream, idata, 56);
if (tmp < 0) {
printf("Could not read index header\n");
return tmp;
@@ -385,13 +384,13 @@ asf_parse_index(asf_file_t *file)
if (index->size < 56) {
/* invalid size for index object */
free(index);
return ASF_ERROR_OBJECT_SIZE;
return ASF_ERROR_INVALID_OBJECT_SIZE;
}
asf_byteio_getGUID(&index->file_id, idata + 24);
index->entry_time_interval = asf_byteio_getQWLE(idata + 40);
index->max_packet_count = asf_byteio_getDWLE(idata + 48);
index->entry_count = asf_byteio_getDWLE(idata + 52);
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);
@@ -416,8 +415,7 @@ asf_parse_index(asf_file_t *file)
free(index);
return ASF_ERROR_OUTOFMEM;
}
tmp = asf_byteio_read(entry_data, entry_data_size, iostream);
tmp = asf_byteio_read(iostream, entry_data, entry_data_size);
if (tmp < 0) {
printf("Could not read entry data\n");
free(index);
@@ -433,8 +431,8 @@ asf_parse_index(asf_file_t *file)
}
for (i=0; i<index->entry_count; i++) {
index->entries[i].packet_index = asf_byteio_getDWLE(entry_data + i*6);
index->entries[i].packet_count = asf_byteio_getWLE(entry_data + i*6 + 4);
index->entries[i].packet_index = GetDWLE(entry_data + i*6);
index->entries[i].packet_count = GetWLE(entry_data + i*6 + 4);
}
free(entry_data);
@@ -1,5 +1,5 @@
/* libasf - An Advanced Systems Format media file parser
* Copyright (C) 2006-2007 Juho Vähä-Herttua
* Copyright (C) 2006-2010 Juho Vähä-Herttua
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -1,107 +0,0 @@
/* libasf - An Advanced Systems Format media file parser
* Copyright (C) 2006-2007 Juho Vähä-Herttua
*
* 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 <stdlib.h>
#include "asf.h"
#include "byteio.h"
/**
* Decode UTF-16LE text from buffer of buflen size and
* allocate a new buffer containing the same string
* encoded as UTF-8. Supports characters outside of BMP
* encoded as an UTF-16 surrogate pair. Returns NULL in
* case of allocation failure or invalid surrogate pair.
* Buflen is in bytes.
*/
char *
asf_utf8_from_utf16le(uint8_t *buf, uint16_t buflen)
{
uint32_t length, pos;
char *ret;
int i;
length = 0;
for (i=0; i<buflen/2; i++) {
uint16_t wchar1, wchar2;
wchar1 = asf_byteio_getWLE(&buf[i*2]);
if (wchar1 >= 0xD800 && wchar1 < 0xDB00) {
i++;
if (i*2 >= buflen) {
/* unexpected end of buffer */
return NULL;
}
wchar2 = asf_byteio_getWLE(&buf[i*2]);
if (wchar2 < 0xDB00 || wchar2 > 0xDFFF) {
/* invalid surrogate pair */
return NULL;
}
length += 4;
} else if (wchar1 > 0x07FF) {
length += 3;
} else if (wchar1 > 0x7F) {
length += 2;
} else {
length++;
}
}
ret = malloc(length + 1);
if (!ret) {
return NULL;
}
pos = 0;
for (i=0; i<buflen/2; i++) {
uint16_t wchar1, wchar2;
uint32_t codepoint;
wchar1 = asf_byteio_getWLE(&buf[i*2]);
if (wchar1 >= 0xD800 && wchar1 < 0xDB00) {
i++;
wchar2 = asf_byteio_getWLE(&buf[i*2]);
codepoint = 0x10000;
codepoint += ((wchar1 & 0x03FF) << 10);
codepoint |= (wchar2 & 0x03FF);
} else {
codepoint = wchar1;
}
if (codepoint > 0xFFFF) {
ret[pos++] = 0xF0 | ((codepoint >> 18) & 0x07);
ret[pos++] = 0x80 | ((codepoint >> 12) & 0x3F);
ret[pos++] = 0x80 | ((codepoint >> 6) & 0x3F);
ret[pos++] = 0x80 | (codepoint & 0x3F);
} else if (codepoint > 0x07FF) {
ret[pos++] = 0xE0 | (codepoint >> 12);
ret[pos++] = 0x80 | ((codepoint >> 6) & 0x3F);
ret[pos++] = 0x80 | (codepoint & 0x3F);
} else if (codepoint > 0x7F) {
ret[pos++] = 0xC0 | (codepoint >> 6);
ret[pos++] = 0x80 | (codepoint & 0x3F);
} else {
ret[pos++] = codepoint;
}
}
ret[length] = '\0';
return ret;
}
@@ -1,5 +1,5 @@
/* libasf - An Advanced Systems Format media file parser
* Copyright (C) 2006-2007 Juho Vähä-Herttua
* Copyright (C) 2006-2010 Juho Vähä-Herttua
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -19,6 +19,92 @@
#ifndef UTF_H
#define UTF_H
char *asf_utf8_from_utf16le(uint8_t *buf, uint16_t buflen);
#include <stdlib.h>
#include "asfint.h"
/**
* Decode UTF-16LE text from buffer of buflen size and
* allocate a new buffer containing the same string
* encoded as UTF-8. Supports characters outside of BMP
* encoded as an UTF-16 surrogate pair. Returns NULL in
* case of allocation failure or invalid surrogate pair.
* Buflen is in bytes.
*/
static char *
asf_utf8_from_utf16le(uint8_t *buf, uint16_t buflen)
{
uint32_t length, pos;
char *ret;
int i;
length = 0;
for (i=0; i<buflen/2; i++) {
uint16_t wchar1, wchar2;
wchar1 = buf[i*2] | (buf[i*2+1] << 8);
if (wchar1 >= 0xD800 && wchar1 < 0xDC00) {
i++;
if (i*2 >= buflen) {
/* unexpected end of buffer */
return NULL;
}
wchar2 = buf[i*2] | (buf[i*2+1] << 8);
if (wchar2 < 0xDB00 || wchar2 > 0xDFFF) {
/* invalid surrogate pair */
return NULL;
}
length += 4;
} else if (wchar1 > 0x07FF) {
length += 3;
} else if (wchar1 > 0x7F) {
length += 2;
} else {
length++;
}
}
ret = malloc(length + 1);
if (!ret) {
return NULL;
}
pos = 0;
for (i=0; i<buflen/2; i++) {
uint16_t wchar1, wchar2;
uint32_t codepoint;
wchar1 = buf[i*2] | (buf[i*2+1] << 8);
if (wchar1 >= 0xD800 && wchar1 < 0xDC00) {
i++;
wchar2 = buf[i*2] | (buf[i*2+1] << 8);
codepoint = 0x10000;
codepoint += ((wchar1 & 0x03FF) << 10);
codepoint |= (wchar2 & 0x03FF);
} else {
codepoint = wchar1;
}
if (codepoint > 0xFFFF) {
ret[pos++] = 0xF0 | ((codepoint >> 18) & 0x07);
ret[pos++] = 0x80 | ((codepoint >> 12) & 0x3F);
ret[pos++] = 0x80 | ((codepoint >> 6) & 0x3F);
ret[pos++] = 0x80 | (codepoint & 0x3F);
} else if (codepoint > 0x07FF) {
ret[pos++] = 0xE0 | (codepoint >> 12);
ret[pos++] = 0x80 | ((codepoint >> 6) & 0x3F);
ret[pos++] = 0x80 | (codepoint & 0x3F);
} else if (codepoint > 0x7F) {
ret[pos++] = 0xC0 | (codepoint >> 6);
ret[pos++] = 0x80 | (codepoint & 0x3F);
} else {
ret[pos++] = codepoint;
}
}
ret[length] = '\0';
return ret;
}
#endif