parent
5fb70bf301
commit
89060c0a8b
@ -1,3 +1,3 @@ |
||||
SUBDIRS = shared src clients data protocol tests
|
||||
SUBDIRS = shared src clients wcap-decode data protocol tests
|
||||
|
||||
DISTCHECK_CONFIGURE_FLAGS = --disable-setuid-install
|
||||
|
@ -0,0 +1,231 @@ |
||||
// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
|
||||
#ifndef MKV_DEFS_HPP |
||||
#define MKV_DEFS_HPP 1 |
||||
|
||||
//Commenting out values not available in webm, but available in matroska
|
||||
|
||||
enum mkv |
||||
{ |
||||
EBML = 0x1A45DFA3, |
||||
EBMLVersion = 0x4286, |
||||
EBMLReadVersion = 0x42F7, |
||||
EBMLMaxIDLength = 0x42F2, |
||||
EBMLMaxSizeLength = 0x42F3, |
||||
DocType = 0x4282, |
||||
DocTypeVersion = 0x4287, |
||||
DocTypeReadVersion = 0x4285, |
||||
// CRC_32 = 0xBF,
|
||||
Void = 0xEC, |
||||
SignatureSlot = 0x1B538667, |
||||
SignatureAlgo = 0x7E8A, |
||||
SignatureHash = 0x7E9A, |
||||
SignaturePublicKey = 0x7EA5, |
||||
Signature = 0x7EB5, |
||||
SignatureElements = 0x7E5B, |
||||
SignatureElementList = 0x7E7B, |
||||
SignedElement = 0x6532, |
||||
//segment
|
||||
Segment = 0x18538067, |
||||
//Meta Seek Information
|
||||
SeekHead = 0x114D9B74, |
||||
Seek = 0x4DBB, |
||||
SeekID = 0x53AB, |
||||
SeekPosition = 0x53AC, |
||||
//Segment Information
|
||||
Info = 0x1549A966, |
||||
// SegmentUID = 0x73A4,
|
||||
// SegmentFilename = 0x7384,
|
||||
// PrevUID = 0x3CB923,
|
||||
// PrevFilename = 0x3C83AB,
|
||||
// NextUID = 0x3EB923,
|
||||
// NextFilename = 0x3E83BB,
|
||||
// SegmentFamily = 0x4444,
|
||||
// ChapterTranslate = 0x6924,
|
||||
// ChapterTranslateEditionUID = 0x69FC,
|
||||
// ChapterTranslateCodec = 0x69BF,
|
||||
// ChapterTranslateID = 0x69A5,
|
||||
TimecodeScale = 0x2AD7B1, |
||||
Segment_Duration = 0x4489, |
||||
DateUTC = 0x4461, |
||||
// Title = 0x7BA9,
|
||||
MuxingApp = 0x4D80, |
||||
WritingApp = 0x5741, |
||||
//Cluster
|
||||
Cluster = 0x1F43B675, |
||||
Timecode = 0xE7, |
||||
// SilentTracks = 0x5854,
|
||||
// SilentTrackNumber = 0x58D7,
|
||||
// Position = 0xA7,
|
||||
PrevSize = 0xAB, |
||||
BlockGroup = 0xA0, |
||||
Block = 0xA1, |
||||
// BlockVirtual = 0xA2,
|
||||
// BlockAdditions = 0x75A1,
|
||||
// BlockMore = 0xA6,
|
||||
// BlockAddID = 0xEE,
|
||||
// BlockAdditional = 0xA5,
|
||||
BlockDuration = 0x9B, |
||||
// ReferencePriority = 0xFA,
|
||||
ReferenceBlock = 0xFB, |
||||
// ReferenceVirtual = 0xFD,
|
||||
// CodecState = 0xA4,
|
||||
// Slices = 0x8E,
|
||||
// TimeSlice = 0xE8,
|
||||
LaceNumber = 0xCC, |
||||
// FrameNumber = 0xCD,
|
||||
// BlockAdditionID = 0xCB,
|
||||
// MkvDelay = 0xCE,
|
||||
// Cluster_Duration = 0xCF,
|
||||
SimpleBlock = 0xA3, |
||||
// EncryptedBlock = 0xAF,
|
||||
//Track
|
||||
Tracks = 0x1654AE6B, |
||||
TrackEntry = 0xAE, |
||||
TrackNumber = 0xD7, |
||||
TrackUID = 0x73C5, |
||||
TrackType = 0x83, |
||||
FlagEnabled = 0xB9, |
||||
FlagDefault = 0x88, |
||||
FlagForced = 0x55AA, |
||||
FlagLacing = 0x9C, |
||||
// MinCache = 0x6DE7,
|
||||
// MaxCache = 0x6DF8,
|
||||
DefaultDuration = 0x23E383, |
||||
// TrackTimecodeScale = 0x23314F,
|
||||
// TrackOffset = 0x537F,
|
||||
// MaxBlockAdditionID = 0x55EE,
|
||||
Name = 0x536E, |
||||
Language = 0x22B59C, |
||||
CodecID = 0x86, |
||||
CodecPrivate = 0x63A2, |
||||
CodecName = 0x258688, |
||||
// AttachmentLink = 0x7446,
|
||||
// CodecSettings = 0x3A9697,
|
||||
// CodecInfoURL = 0x3B4040,
|
||||
// CodecDownloadURL = 0x26B240,
|
||||
// CodecDecodeAll = 0xAA,
|
||||
// TrackOverlay = 0x6FAB,
|
||||
// TrackTranslate = 0x6624,
|
||||
// TrackTranslateEditionUID = 0x66FC,
|
||||
// TrackTranslateCodec = 0x66BF,
|
||||
// TrackTranslateTrackID = 0x66A5,
|
||||
//video
|
||||
Video = 0xE0, |
||||
FlagInterlaced = 0x9A, |
||||
StereoMode = 0x53B8, |
||||
PixelWidth = 0xB0, |
||||
PixelHeight = 0xBA, |
||||
PixelCropBottom = 0x54AA, |
||||
PixelCropTop = 0x54BB, |
||||
PixelCropLeft = 0x54CC, |
||||
PixelCropRight = 0x54DD, |
||||
DisplayWidth = 0x54B0, |
||||
DisplayHeight = 0x54BA, |
||||
DisplayUnit = 0x54B2, |
||||
AspectRatioType = 0x54B3, |
||||
// ColourSpace = 0x2EB524,
|
||||
// GammaValue = 0x2FB523,
|
||||
FrameRate = 0x2383E3, |
||||
//end video
|
||||
//audio
|
||||
Audio = 0xE1, |
||||
SamplingFrequency = 0xB5, |
||||
OutputSamplingFrequency = 0x78B5, |
||||
Channels = 0x9F, |
||||
// ChannelPositions = 0x7D7B,
|
||||
BitDepth = 0x6264, |
||||
//end audio
|
||||
//content encoding
|
||||
// ContentEncodings = 0x6d80,
|
||||
// ContentEncoding = 0x6240,
|
||||
// ContentEncodingOrder = 0x5031,
|
||||
// ContentEncodingScope = 0x5032,
|
||||
// ContentEncodingType = 0x5033,
|
||||
// ContentCompression = 0x5034,
|
||||
// ContentCompAlgo = 0x4254,
|
||||
// ContentCompSettings = 0x4255,
|
||||
// ContentEncryption = 0x5035,
|
||||
// ContentEncAlgo = 0x47e1,
|
||||
// ContentEncKeyID = 0x47e2,
|
||||
// ContentSignature = 0x47e3,
|
||||
// ContentSigKeyID = 0x47e4,
|
||||
// ContentSigAlgo = 0x47e5,
|
||||
// ContentSigHashAlgo = 0x47e6,
|
||||
//end content encoding
|
||||
//Cueing Data
|
||||
Cues = 0x1C53BB6B, |
||||
CuePoint = 0xBB, |
||||
CueTime = 0xB3, |
||||
CueTrackPositions = 0xB7, |
||||
CueTrack = 0xF7, |
||||
CueClusterPosition = 0xF1, |
||||
CueBlockNumber = 0x5378, |
||||
// CueCodecState = 0xEA,
|
||||
// CueReference = 0xDB,
|
||||
// CueRefTime = 0x96,
|
||||
// CueRefCluster = 0x97,
|
||||
// CueRefNumber = 0x535F,
|
||||
// CueRefCodecState = 0xEB,
|
||||
//Attachment
|
||||
// Attachments = 0x1941A469,
|
||||
// AttachedFile = 0x61A7,
|
||||
// FileDescription = 0x467E,
|
||||
// FileName = 0x466E,
|
||||
// FileMimeType = 0x4660,
|
||||
// FileData = 0x465C,
|
||||
// FileUID = 0x46AE,
|
||||
// FileReferral = 0x4675,
|
||||
//Chapters
|
||||
// Chapters = 0x1043A770,
|
||||
// EditionEntry = 0x45B9,
|
||||
// EditionUID = 0x45BC,
|
||||
// EditionFlagHidden = 0x45BD,
|
||||
// EditionFlagDefault = 0x45DB,
|
||||
// EditionFlagOrdered = 0x45DD,
|
||||
// ChapterAtom = 0xB6,
|
||||
// ChapterUID = 0x73C4,
|
||||
// ChapterTimeStart = 0x91,
|
||||
// ChapterTimeEnd = 0x92,
|
||||
// ChapterFlagHidden = 0x98,
|
||||
// ChapterFlagEnabled = 0x4598,
|
||||
// ChapterSegmentUID = 0x6E67,
|
||||
// ChapterSegmentEditionUID = 0x6EBC,
|
||||
// ChapterPhysicalEquiv = 0x63C3,
|
||||
// ChapterTrack = 0x8F,
|
||||
// ChapterTrackNumber = 0x89,
|
||||
// ChapterDisplay = 0x80,
|
||||
// ChapString = 0x85,
|
||||
// ChapLanguage = 0x437C,
|
||||
// ChapCountry = 0x437E,
|
||||
// ChapProcess = 0x6944,
|
||||
// ChapProcessCodecID = 0x6955,
|
||||
// ChapProcessPrivate = 0x450D,
|
||||
// ChapProcessCommand = 0x6911,
|
||||
// ChapProcessTime = 0x6922,
|
||||
// ChapProcessData = 0x6933,
|
||||
//Tagging
|
||||
// Tags = 0x1254C367,
|
||||
// Tag = 0x7373,
|
||||
// Targets = 0x63C0,
|
||||
// TargetTypeValue = 0x68CA,
|
||||
// TargetType = 0x63CA,
|
||||
// Tagging_TrackUID = 0x63C5,
|
||||
// Tagging_EditionUID = 0x63C9,
|
||||
// Tagging_ChapterUID = 0x63C4,
|
||||
// AttachmentUID = 0x63C6,
|
||||
// SimpleTag = 0x67C8,
|
||||
// TagName = 0x45A3,
|
||||
// TagLanguage = 0x447A,
|
||||
// TagDefault = 0x4484,
|
||||
// TagString = 0x4487,
|
||||
// TagBinary = 0x4485,
|
||||
}; |
||||
#endif |
@ -0,0 +1,171 @@ |
||||
// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
|
||||
#include "EbmlWriter.h" |
||||
#include <stdlib.h> |
||||
#include <wchar.h> |
||||
#include <string.h> |
||||
#include <limits.h> |
||||
#if defined(_MSC_VER) |
||||
#define LITERALU64(n) n |
||||
#else |
||||
#define LITERALU64(n) n##LLU |
||||
#endif |
||||
|
||||
void Ebml_WriteLen(EbmlGlobal *glob, long long val) |
||||
{ |
||||
//TODO check and make sure we are not > than 0x0100000000000000LLU
|
||||
unsigned char size = 8; //size in bytes to output
|
||||
unsigned long long minVal = LITERALU64(0x00000000000000ff); //mask to compare for byte size
|
||||
|
||||
for (size = 1; size < 8; size ++) |
||||
{ |
||||
if (val < minVal) |
||||
break; |
||||
|
||||
minVal = (minVal << 7); |
||||
} |
||||
|
||||
val |= (LITERALU64(0x000000000000080) << ((size - 1) * 7)); |
||||
|
||||
Ebml_Serialize(glob, (void *) &val, sizeof(val), size); |
||||
} |
||||
|
||||
void Ebml_WriteString(EbmlGlobal *glob, const char *str) |
||||
{ |
||||
const size_t size_ = strlen(str); |
||||
const unsigned long long size = size_; |
||||
Ebml_WriteLen(glob, size); |
||||
//TODO: it's not clear from the spec whether the nul terminator
|
||||
//should be serialized too. For now we omit the null terminator.
|
||||
Ebml_Write(glob, str, size); |
||||
} |
||||
|
||||
void Ebml_WriteUTF8(EbmlGlobal *glob, const wchar_t *wstr) |
||||
{ |
||||
const size_t strlen = wcslen(wstr); |
||||
|
||||
//TODO: it's not clear from the spec whether the nul terminator
|
||||
//should be serialized too. For now we include it.
|
||||
const unsigned long long size = strlen; |
||||
|
||||
Ebml_WriteLen(glob, size); |
||||
Ebml_Write(glob, wstr, size); |
||||
} |
||||
|
||||
void Ebml_WriteID(EbmlGlobal *glob, unsigned long class_id) |
||||
{ |
||||
int len; |
||||
|
||||
if (class_id >= 0x01000000) |
||||
len = 4; |
||||
else if (class_id >= 0x00010000) |
||||
len = 3; |
||||
else if (class_id >= 0x00000100) |
||||
len = 2; |
||||
else |
||||
len = 1; |
||||
|
||||
Ebml_Serialize(glob, (void *)&class_id, sizeof(class_id), len); |
||||
} |
||||
|
||||
void Ebml_SerializeUnsigned64(EbmlGlobal *glob, unsigned long class_id, uint64_t ui) |
||||
{ |
||||
unsigned char sizeSerialized = 8 | 0x80; |
||||
Ebml_WriteID(glob, class_id); |
||||
Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1); |
||||
Ebml_Serialize(glob, &ui, sizeof(ui), 8); |
||||
} |
||||
|
||||
void Ebml_SerializeUnsigned(EbmlGlobal *glob, unsigned long class_id, unsigned long ui) |
||||
{ |
||||
unsigned char size = 8; //size in bytes to output
|
||||
unsigned char sizeSerialized = 0; |
||||
unsigned long minVal; |
||||
|
||||
Ebml_WriteID(glob, class_id); |
||||
minVal = 0x7fLU; //mask to compare for byte size
|
||||
|
||||
for (size = 1; size < 4; size ++) |
||||
{ |
||||
if (ui < minVal) |
||||
{ |
||||
break; |
||||
} |
||||
|
||||
minVal <<= 7; |
||||
} |
||||
|
||||
sizeSerialized = 0x80 | size; |
||||
Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1); |
||||
Ebml_Serialize(glob, &ui, sizeof(ui), size); |
||||
} |
||||
//TODO: perhaps this is a poor name for this id serializer helper function
|
||||
void Ebml_SerializeBinary(EbmlGlobal *glob, unsigned long class_id, unsigned long bin) |
||||
{ |
||||
int size; |
||||
for (size=4; size > 1; size--) |
||||
{ |
||||
if (bin & 0x000000ff << ((size-1) * 8)) |
||||
break; |
||||
} |
||||
Ebml_WriteID(glob, class_id); |
||||
Ebml_WriteLen(glob, size); |
||||
Ebml_WriteID(glob, bin); |
||||
} |
||||
|
||||
void Ebml_SerializeFloat(EbmlGlobal *glob, unsigned long class_id, double d) |
||||
{ |
||||
unsigned char len = 0x88; |
||||
|
||||
Ebml_WriteID(glob, class_id); |
||||
Ebml_Serialize(glob, &len, sizeof(len), 1); |
||||
Ebml_Serialize(glob, &d, sizeof(d), 8); |
||||
} |
||||
|
||||
void Ebml_WriteSigned16(EbmlGlobal *glob, short val) |
||||
{ |
||||
signed long out = ((val & 0x003FFFFF) | 0x00200000) << 8; |
||||
Ebml_Serialize(glob, &out, sizeof(out), 3); |
||||
} |
||||
|
||||
void Ebml_SerializeString(EbmlGlobal *glob, unsigned long class_id, const char *s) |
||||
{ |
||||
Ebml_WriteID(glob, class_id); |
||||
Ebml_WriteString(glob, s); |
||||
} |
||||
|
||||
void Ebml_SerializeUTF8(EbmlGlobal *glob, unsigned long class_id, wchar_t *s) |
||||
{ |
||||
Ebml_WriteID(glob, class_id); |
||||
Ebml_WriteUTF8(glob, s); |
||||
} |
||||
|
||||
void Ebml_SerializeData(EbmlGlobal *glob, unsigned long class_id, unsigned char *data, unsigned long data_length) |
||||
{ |
||||
Ebml_WriteID(glob, class_id); |
||||
Ebml_WriteLen(glob, data_length); |
||||
Ebml_Write(glob, data, data_length); |
||||
} |
||||
|
||||
void Ebml_WriteVoid(EbmlGlobal *glob, unsigned long vSize) |
||||
{ |
||||
unsigned char tmp = 0; |
||||
unsigned long i = 0; |
||||
|
||||
Ebml_WriteID(glob, 0xEC); |
||||
Ebml_WriteLen(glob, vSize); |
||||
|
||||
for (i = 0; i < vSize; i++) |
||||
{ |
||||
Ebml_Write(glob, &tmp, 1); |
||||
} |
||||
} |
||||
|
||||
//TODO Serialize Date
|
@ -0,0 +1,38 @@ |
||||
#ifndef EBMLWRITER_HPP |
||||
#define EBMLWRITER_HPP |
||||
|
||||
// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
//note: you must define write and serialize functions as well as your own EBML_GLOBAL
|
||||
//These functions MUST be implemented
|
||||
#include <stddef.h> |
||||
#include "vpx/vpx_integer.h" |
||||
|
||||
typedef struct EbmlGlobal EbmlGlobal; |
||||
void Ebml_Serialize(EbmlGlobal *glob, const void *, int, unsigned long); |
||||
void Ebml_Write(EbmlGlobal *glob, const void *, unsigned long); |
||||
/////
|
||||
|
||||
|
||||
void Ebml_WriteLen(EbmlGlobal *glob, long long val); |
||||
void Ebml_WriteString(EbmlGlobal *glob, const char *str); |
||||
void Ebml_WriteUTF8(EbmlGlobal *glob, const wchar_t *wstr); |
||||
void Ebml_WriteID(EbmlGlobal *glob, unsigned long class_id); |
||||
void Ebml_SerializeUnsigned64(EbmlGlobal *glob, unsigned long class_id, uint64_t ui); |
||||
void Ebml_SerializeUnsigned(EbmlGlobal *glob, unsigned long class_id, unsigned long ui); |
||||
void Ebml_SerializeBinary(EbmlGlobal *glob, unsigned long class_id, unsigned long ui); |
||||
void Ebml_SerializeFloat(EbmlGlobal *glob, unsigned long class_id, double d); |
||||
//TODO make this more generic to signed
|
||||
void Ebml_WriteSigned16(EbmlGlobal *glob, short val); |
||||
void Ebml_SerializeString(EbmlGlobal *glob, unsigned long class_id, const char *s); |
||||
void Ebml_SerializeUTF8(EbmlGlobal *glob, unsigned long class_id, wchar_t *s); |
||||
void Ebml_SerializeData(EbmlGlobal *glob, unsigned long class_id, unsigned char *data, unsigned long data_length); |
||||
void Ebml_WriteVoid(EbmlGlobal *glob, unsigned long vSize); |
||||
//TODO need date function
|
||||
#endif |
@ -0,0 +1,265 @@ |
||||
/*
|
||||
* Copyright (c) 2010 The WebM project authors. All Rights Reserved. |
||||
* |
||||
* Use of this source code is governed by a BSD-style license |
||||
* that can be found in the LICENSE file in the root of the source |
||||
* tree. An additional intellectual property rights grant can be found |
||||
* in the file PATENTS. All contributing project authors may |
||||
* be found in the AUTHORS file in the root of the source tree. |
||||
*/ |
||||
|
||||
|
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include <limits.h> |
||||
#include "args.h" |
||||
|
||||
#ifdef _MSC_VER |
||||
#define snprintf _snprintf |
||||
#endif |
||||
|
||||
#if defined(__GNUC__) && __GNUC__ |
||||
extern void die(const char *fmt, ...) __attribute__((noreturn)); |
||||
#else |
||||
extern void die(const char *fmt, ...); |
||||
#endif |
||||
|
||||
|
||||
struct arg arg_init(char **argv) |
||||
{ |
||||
struct arg a; |
||||
|
||||
a.argv = argv; |
||||
a.argv_step = 1; |
||||
a.name = NULL; |
||||
a.val = NULL; |
||||
a.def = NULL; |
||||
return a; |
||||
} |
||||
|
||||
int arg_match(struct arg *arg_, const struct arg_def *def, char **argv) |
||||
{ |
||||
struct arg arg; |
||||
|
||||
if (!argv[0] || argv[0][0] != '-') |
||||
return 0; |
||||
|
||||
arg = arg_init(argv); |
||||
|
||||
if (def->short_name |
||||
&& strlen(arg.argv[0]) == strlen(def->short_name) + 1 |
||||
&& !strcmp(arg.argv[0] + 1, def->short_name)) |
||||
{ |
||||
|
||||
arg.name = arg.argv[0] + 1; |
||||
arg.val = def->has_val ? arg.argv[1] : NULL; |
||||
arg.argv_step = def->has_val ? 2 : 1; |
||||
} |
||||
else if (def->long_name) |
||||
{ |
||||
const size_t name_len = strlen(def->long_name); |
||||
|
||||
if (strlen(arg.argv[0]) >= name_len + 2 |
||||
&& arg.argv[0][1] == '-' |
||||
&& !strncmp(arg.argv[0] + 2, def->long_name, name_len) |
||||
&& (arg.argv[0][name_len+2] == '=' |
||||
|| arg.argv[0][name_len+2] == '\0')) |
||||
{ |
||||
|
||||
arg.name = arg.argv[0] + 2; |
||||
arg.val = arg.name[name_len] == '=' ? arg.name + name_len + 1 : NULL; |
||||
arg.argv_step = 1; |
||||
} |
||||
} |
||||
|
||||
if (arg.name && !arg.val && def->has_val) |
||||
die("Error: option %s requires argument.\n", arg.name); |
||||
|
||||
if (arg.name && arg.val && !def->has_val) |
||||
die("Error: option %s requires no argument.\n", arg.name); |
||||
|
||||
if (arg.name |
||||
&& (arg.val || !def->has_val)) |
||||
{ |
||||
arg.def = def; |
||||
*arg_ = arg; |
||||
return 1; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
|
||||
const char *arg_next(struct arg *arg) |
||||
{ |
||||
if (arg->argv[0]) |
||||
arg->argv += arg->argv_step; |
||||
|
||||
return *arg->argv; |
||||
} |
||||
|
||||
|
||||
char **argv_dup(int argc, const char **argv) |
||||
{ |
||||
char **new_argv = malloc((argc + 1) * sizeof(*argv)); |
||||
|
||||
memcpy(new_argv, argv, argc * sizeof(*argv)); |
||||
new_argv[argc] = NULL; |
||||
return new_argv; |
||||
} |
||||
|
||||
|
||||
void arg_show_usage(FILE *fp, const struct arg_def *const *defs) |
||||
{ |
||||
char option_text[40] = {0}; |
||||
|
||||
for (; *defs; defs++) |
||||
{ |
||||
const struct arg_def *def = *defs; |
||||
char *short_val = def->has_val ? " <arg>" : ""; |
||||
char *long_val = def->has_val ? "=<arg>" : ""; |
||||
|
||||
if (def->short_name && def->long_name) |
||||
{ |
||||
char *comma = def->has_val ? "," : ", "; |
||||
|
||||
snprintf(option_text, 37, "-%s%s%s --%s%6s", |
||||
def->short_name, short_val, comma, |
||||
def->long_name, long_val); |
||||
} |
||||
else if (def->short_name) |
||||
snprintf(option_text, 37, "-%s%s", |
||||
def->short_name, short_val); |
||||
else if (def->long_name) |
||||
snprintf(option_text, 37, " --%s%s", |
||||
def->long_name, long_val); |
||||
|
||||
fprintf(fp, " %-37s\t%s\n", option_text, def->desc); |
||||
|
||||
if(def->enums) |
||||
{ |
||||
const struct arg_enum_list *listptr; |
||||
|
||||
fprintf(fp, " %-37s\t ", ""); |
||||
|
||||
for(listptr = def->enums; listptr->name; listptr++) |
||||
fprintf(fp, "%s%s", listptr->name, |
||||
listptr[1].name ? ", " : "\n"); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
unsigned int arg_parse_uint(const struct arg *arg) |
||||
{ |
||||
long int rawval; |
||||
char *endptr; |
||||
|
||||
rawval = strtol(arg->val, &endptr, 10); |
||||
|
||||
if (arg->val[0] != '\0' && endptr[0] == '\0') |
||||
{ |
||||
if (rawval >= 0 && rawval <= UINT_MAX) |
||||
return rawval; |
||||
|
||||
die("Option %s: Value %ld out of range for unsigned int\n", |
||||
arg->name, rawval); |
||||
} |
||||
|
||||
die("Option %s: Invalid character '%c'\n", arg->name, *endptr); |
||||
return 0; |
||||
} |
||||
|
||||
|
||||
int arg_parse_int(const struct arg *arg) |
||||
{ |
||||
long int rawval; |
||||
char *endptr; |
||||
|
||||
rawval = strtol(arg->val, &endptr, 10); |
||||
|
||||
if (arg->val[0] != '\0' && endptr[0] == '\0') |
||||
{ |
||||
if (rawval >= INT_MIN && rawval <= INT_MAX) |
||||
return rawval; |
||||
|
||||
die("Option %s: Value %ld out of range for signed int\n", |
||||
arg->name, rawval); |
||||
} |
||||
|
||||
die("Option %s: Invalid character '%c'\n", arg->name, *endptr); |
||||
return 0; |
||||
} |
||||
|
||||
|
||||
struct vpx_rational |
||||
{ |
||||
int num; /**< fraction numerator */ |
||||
int den; /**< fraction denominator */ |
||||
}; |
||||
struct vpx_rational arg_parse_rational(const struct arg *arg) |
||||
{ |
||||
long int rawval; |
||||
char *endptr; |
||||
struct vpx_rational rat; |
||||
|
||||
/* parse numerator */ |
||||
rawval = strtol(arg->val, &endptr, 10); |
||||
|
||||
if (arg->val[0] != '\0' && endptr[0] == '/') |
||||
{ |
||||
if (rawval >= INT_MIN && rawval <= INT_MAX) |
||||
rat.num = rawval; |
||||
else die("Option %s: Value %ld out of range for signed int\n", |
||||
arg->name, rawval); |
||||
} |
||||
else die("Option %s: Expected / at '%c'\n", arg->name, *endptr); |
||||
|
||||
/* parse denominator */ |
||||
rawval = strtol(endptr + 1, &endptr, 10); |
||||
|
||||
if (arg->val[0] != '\0' && endptr[0] == '\0') |
||||
{ |
||||
if (rawval >= INT_MIN && rawval <= INT_MAX) |
||||
rat.den = rawval; |
||||
else die("Option %s: Value %ld out of range for signed int\n", |
||||
arg->name, rawval); |
||||
} |
||||
else die("Option %s: Invalid character '%c'\n", arg->name, *endptr); |
||||
|
||||
return rat; |
||||
} |
||||
|
||||
|
||||
int arg_parse_enum(const struct arg *arg) |
||||
{ |
||||
const struct arg_enum_list *listptr; |
||||
long int rawval; |
||||
char *endptr; |
||||
|
||||
/* First see if the value can be parsed as a raw value */ |
||||
rawval = strtol(arg->val, &endptr, 10); |
||||
if (arg->val[0] != '\0' && endptr[0] == '\0') |
||||
{ |
||||
/* Got a raw value, make sure it's valid */ |
||||
for(listptr = arg->def->enums; listptr->name; listptr++) |
||||
if(listptr->val == rawval) |
||||
return rawval; |
||||
} |
||||
|
||||
/* Next see if it can be parsed as a string */ |
||||
for(listptr = arg->def->enums; listptr->name; listptr++) |
||||
if(!strcmp(arg->val, listptr->name)) |
||||
return listptr->val; |
||||
|
||||
die("Option %s: Invalid value '%s'\n", arg->name, arg->val); |
||||
return 0; |
||||
} |
||||
|
||||
|
||||
int arg_parse_enum_or_int(const struct arg *arg) |
||||
{ |
||||
if(arg->def->enums) |
||||
return arg_parse_enum(arg); |
||||
return arg_parse_int(arg); |
||||
} |
@ -0,0 +1,54 @@ |
||||
/*
|
||||
* Copyright (c) 2010 The WebM project authors. All Rights Reserved. |
||||
* |
||||
* Use of this source code is governed by a BSD-style license |
||||
* that can be found in the LICENSE file in the root of the source |
||||
* tree. An additional intellectual property rights grant can be found |
||||
* in the file PATENTS. All contributing project authors may |
||||
* be found in the AUTHORS file in the root of the source tree. |
||||
*/ |
||||
|
||||
|
||||
#ifndef ARGS_H |
||||
#define ARGS_H |
||||
#include <stdio.h> |
||||
|
||||
struct arg |
||||
{ |
||||
char **argv; |
||||
const char *name; |
||||
const char *val; |
||||
unsigned int argv_step; |
||||
const struct arg_def *def; |
||||
}; |
||||
|
||||
struct arg_enum_list |
||||
{ |
||||
const char *name; |
||||
int val; |
||||
}; |
||||
#define ARG_ENUM_LIST_END {0} |
||||
|
||||
typedef struct arg_def |
||||
{ |
||||
const char *short_name; |
||||
const char *long_name; |
||||
int has_val; |
||||
const char *desc; |
||||
const struct arg_enum_list *enums; |
||||
} arg_def_t; |
||||
#define ARG_DEF(s,l,v,d) {s,l,v,d, NULL} |
||||
#define ARG_DEF_ENUM(s,l,v,d,e) {s,l,v,d,e} |
||||
#define ARG_DEF_LIST_END {0} |
||||
|
||||
struct arg arg_init(char **argv); |
||||
int arg_match(struct arg *arg_, const struct arg_def *def, char **argv); |
||||
const char *arg_next(struct arg *arg); |
||||
void arg_show_usage(FILE *fp, const struct arg_def *const *defs); |
||||
char **argv_dup(int argc, const char **argv); |
||||
|
||||
unsigned int arg_parse_uint(const struct arg *arg); |
||||
int arg_parse_int(const struct arg *arg); |
||||
struct vpx_rational arg_parse_rational(const struct arg *arg); |
||||
int arg_parse_enum_or_int(const struct arg *arg); |
||||
#endif |
@ -0,0 +1,234 @@ |
||||
/*
|
||||
* Copyright (c) 2010 The WebM project authors. All Rights Reserved. |
||||
* |
||||
* Use of this source code is governed by a BSD-style license |
||||
* that can be found in the LICENSE file in the root of the source |
||||
* tree. An additional intellectual property rights grant can be found |
||||
* in the file PATENTS. All contributing project authors may |
||||
* be found in the AUTHORS file in the root of the source tree. |
||||
*/ |
||||
|
||||
|
||||
/* \file
|
||||
* \brief Provides portable memory access primitives |
||||
* |
||||
* This function provides portable primitives for getting and setting of |
||||
* signed and unsigned integers in 16, 24, and 32 bit sizes. The operations |
||||
* can be performed on unaligned data regardless of hardware support for |
||||
* unaligned accesses. |
||||
* |
||||
* The type used to pass the integral values may be changed by defining |
||||
* MEM_VALUE_T with the appropriate type. The type given must be an integral |
||||
* numeric type. |
||||
* |
||||
* The actual functions instantiated have the MEM_VALUE_T type name pasted |
||||
* on to the symbol name. This allows the developer to instantiate these |
||||
* operations for multiple types within the same translation unit. This is |
||||
* of somewhat questionable utility, but the capability exists nonetheless. |
||||
* Users not making use of this functionality should call the functions |
||||
* without the type name appended, and the preprocessor will take care of |
||||
* it. |
||||
* |
||||
* NOTE: This code is not supported on platforms where char > 1 octet ATM. |
||||
*/ |
||||
|
||||
#ifndef MAU_T |
||||
/* Minimum Access Unit for this target */ |
||||
#define MAU_T unsigned char |
||||
#endif |
||||
|
||||
#ifndef MEM_VALUE_T |
||||
#define MEM_VALUE_T int |
||||
#endif |
||||
|
||||
#undef MEM_VALUE_T_SZ_BITS |
||||
#define MEM_VALUE_T_SZ_BITS (sizeof(MEM_VALUE_T) << 3) |
||||
|
||||
#undef mem_ops_wrap_symbol |
||||
#define mem_ops_wrap_symbol(fn) mem_ops_wrap_symbol2(fn, MEM_VALUE_T) |
||||
#undef mem_ops_wrap_symbol2 |
||||
#define mem_ops_wrap_symbol2(fn,typ) mem_ops_wrap_symbol3(fn,typ) |
||||
#undef mem_ops_wrap_symbol3 |
||||
#define mem_ops_wrap_symbol3(fn,typ) fn##_as_##typ |
||||
|
||||
/*
|
||||
* Include aligned access routines |
||||
*/ |
||||
#define INCLUDED_BY_MEM_OPS_H |
||||
#include "mem_ops_aligned.h" |
||||
#undef INCLUDED_BY_MEM_OPS_H |
||||
|
||||
#undef mem_get_be16 |
||||
#define mem_get_be16 mem_ops_wrap_symbol(mem_get_be16) |
||||
static unsigned MEM_VALUE_T mem_get_be16(const void *vmem) |
||||
{ |
||||
unsigned MEM_VALUE_T val; |
||||
const MAU_T *mem = (const MAU_T *)vmem; |
||||
|
||||
val = mem[0] << 8; |
||||
val |= mem[1]; |
||||
return val; |
||||
} |
||||
|
||||
#undef mem_get_be24 |
||||
#define mem_get_be24 mem_ops_wrap_symbol(mem_get_be24) |
||||
static unsigned MEM_VALUE_T mem_get_be24(const void *vmem) |
||||
{ |
||||
unsigned MEM_VALUE_T val; |
||||
const MAU_T *mem = (const MAU_T *)vmem; |
||||
|
||||
val = mem[0] << 16; |
||||
val |= mem[1] << 8; |
||||
val |= mem[2]; |
||||
return val; |
||||
} |
||||
|
||||
#undef mem_get_be32 |
||||
#define mem_get_be32 mem_ops_wrap_symbol(mem_get_be32) |
||||
static unsigned MEM_VALUE_T mem_get_be32(const void *vmem) |
||||
{ |
||||
unsigned MEM_VALUE_T val; |
||||
const MAU_T *mem = (const MAU_T *)vmem; |
||||
|
||||
val = mem[0] << 24; |
||||
val |= mem[1] << 16; |
||||
val |= mem[2] << 8; |
||||
val |= mem[3]; |
||||
return val; |
||||
} |
||||
|
||||
#undef mem_get_le16 |
||||
#define mem_get_le16 mem_ops_wrap_symbol(mem_get_le16) |
||||
static unsigned MEM_VALUE_T mem_get_le16(const void *vmem) |
||||
{ |
||||
unsigned MEM_VALUE_T val; |
||||
const MAU_T *mem = (const MAU_T *)vmem; |
||||
|
||||
val = mem[1] << 8; |
||||
val |= mem[0]; |
||||
return val; |
||||
} |
||||
|
||||
#undef mem_get_le24 |
||||
#define mem_get_le24 mem_ops_wrap_symbol(mem_get_le24) |
||||
static unsigned MEM_VALUE_T mem_get_le24(const void *vmem) |
||||
{ |
||||
unsigned MEM_VALUE_T val; |
||||
const MAU_T *mem = (const MAU_T *)vmem; |
||||
|
||||
val = mem[2] << 16; |
||||
val |= mem[1] << 8; |
||||
val |= mem[0]; |
||||
return val; |
||||
} |
||||
|
||||
#undef mem_get_le32 |
||||
#define mem_get_le32 mem_ops_wrap_symbol(mem_get_le32) |
||||
static unsigned MEM_VALUE_T mem_get_le32(const void *vmem) |
||||
{ |
||||
unsigned MEM_VALUE_T val; |
||||
const MAU_T *mem = (const MAU_T *)vmem; |
||||
|
||||
val = mem[3] << 24; |
||||
val |= mem[2] << 16; |
||||
val |= mem[1] << 8; |
||||
val |= mem[0]; |
||||
return val; |
||||
} |
||||
|
||||
#define mem_get_s_generic(end,sz) \ |
||||
static signed MEM_VALUE_T mem_get_s##end##sz(const void *vmem) {\
|
||||
const MAU_T *mem = (const MAU_T*)vmem;\
|
||||
signed MEM_VALUE_T val = mem_get_##end##sz(mem);\
|
||||
return (val << (MEM_VALUE_T_SZ_BITS - sz)) >> (MEM_VALUE_T_SZ_BITS - sz);\
|
||||
} |
||||
|
||||
#undef mem_get_sbe16 |
||||
#define mem_get_sbe16 mem_ops_wrap_symbol(mem_get_sbe16) |
||||
mem_get_s_generic(be, 16); |
||||
|
||||
#undef mem_get_sbe24 |
||||
#define mem_get_sbe24 mem_ops_wrap_symbol(mem_get_sbe24) |
||||
mem_get_s_generic(be, 24); |
||||
|
||||
#undef mem_get_sbe32 |
||||
#define mem_get_sbe32 mem_ops_wrap_symbol(mem_get_sbe32) |
||||
mem_get_s_generic(be, 32); |
||||
|
||||
#undef mem_get_sle16 |
||||
#define mem_get_sle16 mem_ops_wrap_symbol(mem_get_sle16) |
||||
mem_get_s_generic(le, 16); |
||||
|
||||
#undef mem_get_sle24 |
||||
#define mem_get_sle24 mem_ops_wrap_symbol(mem_get_sle24) |
||||
mem_get_s_generic(le, 24); |
||||
|
||||
#undef mem_get_sle32 |
||||
#define mem_get_sle32 mem_ops_wrap_symbol(mem_get_sle32) |
||||
mem_get_s_generic(le, 32); |
||||
|
||||
#undef mem_put_be16 |
||||
#define mem_put_be16 mem_ops_wrap_symbol(mem_put_be16) |
||||
static void mem_put_be16(void *vmem, MEM_VALUE_T val) |
||||
{ |
||||
MAU_T *mem = (MAU_T *)vmem; |
||||
|
||||
mem[0] = (val >> 8) & 0xff; |
||||
mem[1] = (val >> 0) & 0xff; |
||||
} |
||||
|
||||
#undef mem_put_be24 |
||||
#define mem_put_be24 mem_ops_wrap_symbol(mem_put_be24) |
||||
static void mem_put_be24(void *vmem, MEM_VALUE_T val) |
||||
{ |
||||
MAU_T *mem = (MAU_T *)vmem; |
||||
|
||||
mem[0] = (val >> 16) & 0xff; |
||||
mem[1] = (val >> 8) & 0xff; |
||||
mem[2] = (val >> 0) & 0xff; |
||||
} |
||||
|
||||
#undef mem_put_be32 |
||||
#define mem_put_be32 mem_ops_wrap_symbol(mem_put_be32) |
||||
static void mem_put_be32(void *vmem, MEM_VALUE_T val) |
||||
{ |
||||
MAU_T *mem = (MAU_T *)vmem; |
||||
|
||||
mem[0] = (val >> 24) & 0xff; |
||||
mem[1] = (val >> 16) & 0xff; |
||||
mem[2] = (val >> 8) & 0xff; |
||||
mem[3] = (val >> 0) & 0xff; |
||||
} |
||||
|
||||
#undef mem_put_le16 |
||||
#define mem_put_le16 mem_ops_wrap_symbol(mem_put_le16) |
||||
static void mem_put_le16(void *vmem, MEM_VALUE_T val) |
||||
{ |
||||
MAU_T *mem = (MAU_T *)vmem; |
||||
|
||||
mem[0] = (val >> 0) & 0xff; |
||||
mem[1] = (val >> 8) & 0xff; |
||||
} |
||||
|
||||
#undef mem_put_le24 |
||||
#define mem_put_le24 mem_ops_wrap_symbol(mem_put_le24) |
||||
static void mem_put_le24(void *vmem, MEM_VALUE_T val) |
||||
{ |
||||
MAU_T *mem = (MAU_T *)vmem; |
||||
|
||||
mem[0] = (val >> 0) & 0xff; |
||||
mem[1] = (val >> 8) & 0xff; |
||||
mem[2] = (val >> 16) & 0xff; |
||||
} |
||||
|
||||
#undef mem_put_le32 |
||||
#define mem_put_le32 mem_ops_wrap_symbol(mem_put_le32) |
||||
static void mem_put_le32(void *vmem, MEM_VALUE_T val) |
||||
{ |
||||
MAU_T *mem = (MAU_T *)vmem; |
||||
|
||||
mem[0] = (val >> 0) & 0xff; |
||||
mem[1] = (val >> 8) & 0xff; |
||||
mem[2] = (val >> 16) & 0xff; |
||||
mem[3] = (val >> 24) & 0xff; |
||||
} |
@ -0,0 +1,157 @@ |
||||
/*
|
||||
* Copyright (c) 2010 The WebM project authors. All Rights Reserved. |
||||
* |
||||
* Use of this source code is governed by a BSD-style license |
||||
* that can be found in the LICENSE file in the root of the source |
||||
* tree. An additional intellectual property rights grant can be found |
||||
* in the file PATENTS. All contributing project authors may |
||||
* be found in the AUTHORS file in the root of the source tree. |
||||
*/ |
||||
|
||||
|
||||
/* \file
|
||||
* \brief Provides portable memory access primitives for operating on aligned |
||||
* data |
||||
* |
||||
* This file is split from mem_ops.h for easier maintenance. See mem_ops.h |
||||
* for a more detailed description of these primitives. |
||||
*/ |
||||
#ifndef INCLUDED_BY_MEM_OPS_H |
||||
#error Include mem_ops.h, not mem_ops_aligned.h directly. |
||||
#endif |
||||
|
||||
/* Architectures that provide instructions for doing this byte swapping
|
||||
* could redefine these macros. |
||||
*/ |
||||
#define swap_endian_16(val,raw) do {\ |
||||
val = ((raw>>8) & 0x00ff) \
|
||||
| ((raw<<8) & 0xff00);\
|
||||
} while(0) |
||||
#define swap_endian_32(val,raw) do {\ |
||||
val = ((raw>>24) & 0x000000ff) \
|
||||
| ((raw>>8) & 0x0000ff00) \
|
||||
| ((raw<<8) & 0x00ff0000) \
|
||||
| ((raw<<24) & 0xff000000); \
|
||||
} while(0) |
||||
#define swap_endian_16_se(val,raw) do {\ |
||||
swap_endian_16(val,raw);\
|
||||
val = ((val << 16) >> 16);\
|
||||
} while(0) |
||||
#define swap_endian_32_se(val,raw) swap_endian_32(val,raw) |
||||
|
||||
#define mem_get_ne_aligned_generic(end,sz) \ |
||||
static unsigned MEM_VALUE_T mem_get_##end##sz##_aligned(const void *vmem) {\
|
||||
const uint##sz##_t *mem = (const uint##sz##_t *)vmem;\
|
||||
return *mem;\
|
||||
} |
||||
|
||||
#define mem_get_sne_aligned_generic(end,sz) \ |
||||
static signed MEM_VALUE_T mem_get_s##end##sz##_aligned(const void *vmem) {\
|
||||
const int##sz##_t *mem = (const int##sz##_t *)vmem;\
|
||||
return *mem;\
|
||||
} |
||||
|
||||
#define mem_get_se_aligned_generic(end,sz) \ |
||||
static unsigned MEM_VALUE_T mem_get_##end##sz##_aligned(const void *vmem) {\
|
||||
const uint##sz##_t *mem = (const uint##sz##_t *)vmem;\
|
||||
unsigned MEM_VALUE_T val, raw = *mem;\
|
||||
swap_endian_##sz(val,raw);\
|
||||
return val;\
|
||||
} |
||||
|
||||
#define mem_get_sse_aligned_generic(end,sz) \ |
||||
static signed MEM_VALUE_T mem_get_s##end##sz##_aligned(const void *vmem) {\
|
||||
const int##sz##_t *mem = (const int##sz##_t *)vmem;\
|
||||
unsigned MEM_VALUE_T val, raw = *mem;\
|
||||
swap_endian_##sz##_se(val,raw);\
|
||||
return val;\
|
||||
} |
||||
|
||||
#define mem_put_ne_aligned_generic(end,sz) \ |
||||
static void mem_put_##end##sz##_aligned(void *vmem, MEM_VALUE_T val) {\
|
||||
uint##sz##_t *mem = (uint##sz##_t *)vmem;\
|
||||
*mem = (uint##sz##_t)val;\
|
||||
} |
||||
|
||||
#define mem_put_se_aligned_generic(end,sz) \ |
||||
static void mem_put_##end##sz##_aligned(void *vmem, MEM_VALUE_T val) {\
|
||||
uint##sz##_t *mem = (uint##sz##_t *)vmem, raw;\
|
||||
swap_endian_##sz(raw,val);\
|
||||
*mem = (uint##sz##_t)raw;\
|
||||
} |
||||
|
||||
#include "vpx_config.h" |
||||
#if CONFIG_BIG_ENDIAN |
||||
#define mem_get_be_aligned_generic(sz) mem_get_ne_aligned_generic(be,sz) |
||||
#define mem_get_sbe_aligned_generic(sz) mem_get_sne_aligned_generic(be,sz) |
||||
#define mem_get_le_aligned_generic(sz) mem_get_se_aligned_generic(le,sz) |
||||
#define mem_get_sle_aligned_generic(sz) mem_get_sse_aligned_generic(le,sz) |
||||
#define mem_put_be_aligned_generic(sz) mem_put_ne_aligned_generic(be,sz) |
||||
#define mem_put_le_aligned_generic(sz) mem_put_se_aligned_generic(le,sz) |
||||
#else |
||||
#define mem_get_be_aligned_generic(sz) mem_get_se_aligned_generic(be,sz) |
||||
#define mem_get_sbe_aligned_generic(sz) mem_get_sse_aligned_generic(be,sz) |
||||
#define mem_get_le_aligned_generic(sz) mem_get_ne_aligned_generic(le,sz) |
||||
#define mem_get_sle_aligned_generic(sz) mem_get_sne_aligned_generic(le,sz) |
||||
#define mem_put_be_aligned_generic(sz) mem_put_se_aligned_generic(be,sz) |
||||
#define mem_put_le_aligned_generic(sz) mem_put_ne_aligned_generic(le,sz) |
||||
#endif |
||||
|
||||
#undef mem_get_be16_aligned |
||||
#define mem_get_be16_aligned mem_ops_wrap_symbol(mem_get_be16_aligned) |
||||
mem_get_be_aligned_generic(16); |
||||
|
||||
#undef mem_get_be32_aligned |
||||
#define mem_get_be32_aligned mem_ops_wrap_symbol(mem_get_be32_aligned) |
||||
mem_get_be_aligned_generic(32); |
||||
|
||||
#undef mem_get_le16_aligned |
||||
#define mem_get_le16_aligned mem_ops_wrap_symbol(mem_get_le16_aligned) |
||||
mem_get_le_aligned_generic(16); |
||||
|
||||
#undef mem_get_le32_aligned |
||||
#define mem_get_le32_aligned mem_ops_wrap_symbol(mem_get_le32_aligned) |
||||
mem_get_le_aligned_generic(32); |
||||
|
||||
#undef mem_get_sbe16_aligned |
||||
#define mem_get_sbe16_aligned mem_ops_wrap_symbol(mem_get_sbe16_aligned) |
||||
mem_get_sbe_aligned_generic(16); |
||||
|
||||
#undef mem_get_sbe32_aligned |
||||
#define mem_get_sbe32_aligned mem_ops_wrap_symbol(mem_get_sbe32_aligned) |
||||
mem_get_sbe_aligned_generic(32); |
||||
|
||||
#undef mem_get_sle16_aligned |
||||
#define mem_get_sle16_aligned mem_ops_wrap_symbol(mem_get_sle16_aligned) |
||||
mem_get_sle_aligned_generic(16); |
||||
|
||||
#undef mem_get_sle32_aligned |
||||
#define mem_get_sle32_aligned mem_ops_wrap_symbol(mem_get_sle32_aligned) |
||||
mem_get_sle_aligned_generic(32); |
||||
|
||||
#undef mem_put_be16_aligned |
||||
#define mem_put_be16_aligned mem_ops_wrap_symbol(mem_put_be16_aligned) |
||||
mem_put_be_aligned_generic(16); |
||||
|
||||
#undef mem_put_be32_aligned |
||||
#define mem_put_be32_aligned mem_ops_wrap_symbol(mem_put_be32_aligned) |
||||
mem_put_be_aligned_generic(32); |
||||
|
||||
#undef mem_put_le16_aligned |
||||
#define mem_put_le16_aligned mem_ops_wrap_symbol(mem_put_le16_aligned) |
||||
mem_put_le_aligned_generic(16); |
||||
|
||||
#undef mem_put_le32_aligned |
||||
#define mem_put_le32_aligned mem_ops_wrap_symbol(mem_put_le32_aligned) |
||||
mem_put_le_aligned_generic(32); |
||||
|
||||
#undef mem_get_ne_aligned_generic |
||||
#undef mem_get_se_aligned_generic |
||||
#undef mem_get_sne_aligned_generic |
||||
#undef mem_get_sse_aligned_generic |
||||
#undef mem_put_ne_aligned_generic |
||||
#undef mem_put_se_aligned_generic |
||||
#undef swap_endian_16 |
||||
#undef swap_endian_32 |
||||
#undef swap_endian_16_se |
||||
#undef swap_endian_32_se |
@ -0,0 +1,30 @@ |
||||
/*
|
||||
* Copyright (c) 2010 The WebM project authors. All Rights Reserved. |
||||
* |
||||
* Use of this source code is governed by a BSD-style license |
||||
* that can be found in the LICENSE file in the root of the source |
||||
* tree. An additional intellectual property rights grant can be found |
||||
* in the file PATENTS. All contributing project authors may |
||||
* be found in the AUTHORS file in the root of the source tree. |
||||
*/ |
||||
#include <stdio.h> |
||||
#include "tools_common.h" |
||||
#if defined(_WIN32) || defined(__OS2__) |
||||
#include <io.h> |
||||
#include <fcntl.h> |
||||
|
||||
#ifdef __OS2__ |
||||
#define _setmode setmode |
||||
#define _fileno fileno |
||||
#define _O_BINARY O_BINARY |
||||
#endif |
||||
#endif |
||||
|
||||
FILE* set_binary_mode(FILE *stream) |
||||
{ |
||||
(void)stream; |
||||
#if defined(_WIN32) || defined(__OS2__) |
||||
_setmode(_fileno(stream), _O_BINARY); |
||||
#endif |
||||
return stream; |
||||
} |
@ -0,0 +1,16 @@ |
||||
/*
|
||||
* Copyright (c) 2010 The WebM project authors. All Rights Reserved. |
||||
* |
||||
* Use of this source code is governed by a BSD-style license |
||||
* that can be found in the LICENSE file in the root of the source |
||||
* tree. An additional intellectual property rights grant can be found |
||||
* in the file PATENTS. All contributing project authors may |
||||
* be found in the AUTHORS file in the root of the source tree. |
||||
*/ |
||||
#ifndef TOOLS_COMMON_H |
||||
#define TOOLS_COMMON_H |
||||
|
||||
/* Sets a stdio stream into binary mode */ |
||||
FILE* set_binary_mode(FILE *stream); |
||||
|
||||
#endif |
@ -0,0 +1,120 @@ |
||||
/*
|
||||
* Copyright (c) 2010 The WebM project authors. All Rights Reserved. |
||||
* |
||||
* Use of this source code is governed by a BSD-style license |
||||
* that can be found in the LICENSE file in the root of the source |
||||
* tree. An additional intellectual property rights grant can be found |
||||
* in the file PATENTS. All contributing project authors may |
||||
* be found in the AUTHORS file in the root of the source tree. |
||||
*/ |
||||
|
||||
|
||||
#ifndef VPX_TIMER_H |
||||
#define VPX_TIMER_H |
||||
#include "vpx/vpx_integer.h" |
||||
|
||||
#if CONFIG_OS_SUPPORT |
||||
|
||||
#if defined(_WIN32) |
||||
/*
|
||||
* Win32 specific includes |
||||
*/ |
||||
#ifndef WIN32_LEAN_AND_MEAN |
||||
#define WIN32_LEAN_AND_MEAN |
||||
#endif |
||||
#include <windows.h> |
||||
#else |
||||
/*
|
||||
* POSIX specific includes |
||||
*/ |
||||
#include <sys/time.h> |
||||
|
||||
/* timersub is not provided by msys at this time. */ |
||||
#ifndef timersub |
||||
#define timersub(a, b, result) \ |
||||
do { \
|
||||
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
|
||||
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
|
||||
if ((result)->tv_usec < 0) { \
|
||||
--(result)->tv_sec; \
|
||||
(result)->tv_usec += 1000000; \
|
||||
} \
|
||||
} while (0) |
||||
#endif |
||||
#endif |
||||
|
||||
|
||||
struct vpx_usec_timer |
||||
{ |
||||
#if defined(_WIN32) |
||||
LARGE_INTEGER begin, end; |
||||
#else |
||||
struct timeval begin, end; |
||||
#endif |
||||
}; |
||||
|
||||
|
||||
static void |
||||
vpx_usec_timer_start(struct vpx_usec_timer *t) |
||||
{ |
||||
#if defined(_WIN32) |
||||
QueryPerformanceCounter(&t->begin); |
||||
#else |
||||
gettimeofday(&t->begin, NULL); |
||||
#endif |
||||
} |
||||
|
||||
|
||||
static void |
||||
vpx_usec_timer_mark(struct vpx_usec_timer *t) |
||||
{ |
||||
#if defined(_WIN32) |
||||
QueryPerformanceCounter(&t->end); |
||||
#else |
||||
gettimeofday(&t->end, NULL); |
||||
#endif |
||||
} |
||||
|
||||
|
||||
static int64_t |
||||
vpx_usec_timer_elapsed(struct vpx_usec_timer *t) |
||||
{ |
||||
#if defined(_WIN32) |
||||
LARGE_INTEGER freq, diff; |
||||
|
||||
diff.QuadPart = t->end.QuadPart - t->begin.QuadPart; |
||||
|
||||
QueryPerformanceFrequency(&freq); |
||||
return diff.QuadPart * 1000000 / freq.QuadPart; |
||||
#else |
||||
struct timeval diff; |
||||
|
||||
timersub(&t->end, &t->begin, &diff); |
||||
return diff.tv_sec * 1000000 + diff.tv_usec; |
||||
#endif |
||||
} |
||||
|
||||
#else /* CONFIG_OS_SUPPORT = 0*/ |
||||
|
||||
/* Empty timer functions if CONFIG_OS_SUPPORT = 0 */ |
||||
#ifndef timersub |
||||
#define timersub(a, b, result) |
||||
#endif |
||||
|
||||
struct vpx_usec_timer |
||||
{ |
||||
void *dummy; |
||||
}; |
||||
|
||||
static void |
||||
vpx_usec_timer_start(struct vpx_usec_timer *t) { } |
||||
|
||||
static void |
||||
vpx_usec_timer_mark(struct vpx_usec_timer *t) { } |
||||
|
||||
static long |
||||
vpx_usec_timer_elapsed(struct vpx_usec_timer *t) { return 0; } |
||||
|
||||
#endif /* CONFIG_OS_SUPPORT */ |
||||
|
||||
#endif |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,218 @@ |
||||
/*
|
||||
* Copyright © 2012 Intel Corporation |
||||
* |
||||
* Permission to use, copy, modify, distribute, and sell this software and |
||||
* its documentation for any purpose is hereby granted without fee, provided |
||||
* that the above copyright notice appear in all copies and that both that |
||||
* copyright notice and this permission notice appear in supporting |
||||
* documentation, and that the name of the copyright holders not be used in |
||||
* advertising or publicity pertaining to distribution of the software |
||||
* without specific, written prior permission. The copyright holders make |
||||
* no representations about the suitability of this software for any |
||||
* purpose. It is provided "as is" without express or implied warranty. |
||||
* |
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS |
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND |
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY |
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER |
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF |
||||
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
*/ |
||||
|
||||
#include <stdlib.h> |
||||
#include <stdio.h> |
||||
#include <stdint.h> |
||||
#include <sys/mman.h> |
||||
#include <sys/mman.h> |
||||
#include <sys/types.h> |
||||
#include <sys/stat.h> |
||||
#include <unistd.h> |
||||
#include <string.h> |
||||
#include <fcntl.h> |
||||
|
||||
#include <cairo.h> |
||||
|
||||
struct wcap_header { |
||||
uint32_t width, height; |
||||
}; |
||||
|
||||
struct wcap_frame_header { |
||||
uint32_t msecs; |
||||
uint32_t nrects; |
||||
}; |
||||
|
||||
struct wcap_rectangle { |
||||
int32_t x1, y1, x2, y2; |
||||
}; |
||||
|
||||
struct wcap_decoder { |
||||
int fd; |
||||
size_t size; |
||||
void *map, *p, *end; |
||||
uint32_t *frame; |
||||
int width, height; |
||||
}; |
||||
|
||||
static void |
||||
wcap_decoder_decode_rectangle(struct wcap_decoder *decoder, |
||||
struct wcap_rectangle *rect) |
||||
{ |
||||
uint32_t v, *p = decoder->p, *d; |
||||
int width = rect->x2 - rect->x1, height = rect->y2 - rect->y1; |
||||
int x, i, j, k, l, count = width * height; |
||||
|
||||
d = decoder->frame + (rect->y2 - 1) * decoder->width; |
||||
x = rect->x1; |
||||
i = 0; |
||||
while (i < count) { |
||||
v = *p++; |
||||
l = v >> 24; |
||||
if (l < 0xe0) { |
||||
j = l + 1; |
||||
} else { |
||||
j = 1 << (l - 0xe0 + 7); |
||||
} |
||||
|
||||
for (k = 0; k < j; k++) { |
||||
d[x] = (d[x] + v) | 0xff000000; |
||||
x++; |
||||
if (x == rect->x2) { |
||||
x = rect->x1; |
||||
d -= decoder->width; |
||||
} |
||||
} |
||||
i += j; |
||||
} |
||||
|
||||
if (i != count) |
||||
printf("rle encoding longer than expected (%d expected %d)\n", |
||||
i, count); |
||||
|
||||
decoder->p = p; |
||||
} |
||||
|
||||
static int |
||||
wcap_decoder_get_frame(struct wcap_decoder *decoder) |
||||
{ |
||||
struct wcap_rectangle *rects; |
||||
struct wcap_frame_header *header; |
||||
uint32_t *s; |
||||
uint32_t i; |
||||
int width, height; |
||||
|
||||
if (decoder->p == decoder->end) |
||||
return 0; |
||||
|
||||
header = decoder->p; |
||||
|
||||
rects = (void *) (header + 1); |
||||
decoder->p = (uint32_t *) (rects + header->nrects); |
||||
for (i = 0; i < header->nrects; i++) { |
||||
width = rects[i].x2 - rects[i].x1; |
||||
height = rects[i].y2 - rects[i].y1; |
||||
wcap_decoder_decode_rectangle(decoder, &rects[i]); |
||||
} |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
struct wcap_decoder * |
||||
wcap_decoder_create(const char *filename) |
||||
{ |
||||
struct wcap_decoder *decoder; |
||||
struct wcap_header *header; |
||||
int frame_size; |
||||
struct stat buf; |
||||
|
||||
decoder = malloc(sizeof *decoder); |
||||
if (decoder == NULL) |
||||
return NULL; |
||||
|
||||
decoder->fd = open(filename, O_RDONLY); |
||||
if (decoder->fd == -1) |
||||
return NULL; |
||||
|
||||
fstat(decoder->fd, &buf); |
||||
decoder->size = buf.st_size; |
||||
decoder->map = mmap(NULL, decoder->size, |
||||
PROT_READ, MAP_PRIVATE, decoder->fd, 0); |
||||
|
||||
header = decoder->map; |
||||
decoder->width = header->width; |
||||
decoder->height = header->height; |
||||
decoder->p = header + 1; |
||||
decoder->end = decoder->map + decoder->size; |
||||
|
||||
frame_size = header->width * header->height * 4; |
||||
decoder->frame = malloc(frame_size); |
||||
memset(decoder->frame, 0, frame_size); |
||||
|
||||
return decoder; |
||||
} |
||||
|
||||
void |
||||
wcap_decoder_destroy(struct wcap_decoder *decoder) |
||||
{ |
||||
munmap(decoder->map, decoder->size); |
||||
free(decoder->frame); |
||||
free(decoder); |
||||
} |
||||
|
||||
static void |
||||
write_png(struct wcap_decoder *decoder, const char *filename) |
||||
{ |
||||
cairo_surface_t *surface; |
||||
|
||||
surface = cairo_image_surface_create_for_data((unsigned char *) decoder->frame, |
||||
CAIRO_FORMAT_ARGB32, |
||||
decoder->width, |
||||
decoder->height, |
||||
decoder->width * 4); |
||||
cairo_surface_write_to_png(surface, filename); |
||||
cairo_surface_destroy(surface); |
||||
} |
||||
|
||||
static void |
||||
write_all_pngs(struct wcap_decoder *decoder, int frame) |
||||
{ |
||||
char filename[200]; |
||||
int i; |
||||
|
||||
i = 0; |
||||
while (wcap_decoder_get_frame(decoder)) { |
||||
if (i == frame || frame == -1) { |
||||
snprintf(filename, sizeof filename, |
||||
"wcap-frame-%d.png", i); |
||||
write_png(decoder, filename); |
||||
printf("wrote %s\n", filename); |
||||
} |
||||
i++; |
||||
} |
||||
} |
||||
|
||||
int main(int argc, char *argv[]) |
||||
{ |
||||
struct wcap_decoder *decoder; |
||||
int i, output_frame; |
||||
|
||||
if (argc != 2 && argc != 3) { |
||||
fprintf(stderr, "usage: wcap-decode WCAP_FILE [FRAME]\n"); |
||||
return 1; |
||||
}
|
||||
|
||||
decoder = wcap_decoder_create(argv[1]); |
||||
output_frame = -1; |
||||
if (argc == 3) |
||||
output_frame = strtol(argv[2], NULL, 0); |
||||
|
||||
if (0) |
||||
write_all_pngs(decoder, -1); |
||||
else |
||||
write_webm(decoder); |
||||
|
||||
printf("wcap file: size %dx%d, %d frames\n", |
||||
decoder->width, decoder->height, i); |
||||
|
||||
wcap_decoder_destroy(decoder); |
||||
} |
@ -0,0 +1,871 @@ |
||||
/*
|
||||
* Copyright (c) 2010 The WebM project authors. All Rights Reserved. |
||||
* |
||||
* Use of this source code is governed by a BSD-style license |
||||
* that can be found in the LICENSE file in the root of the source |
||||
* tree. An additional intellectual property rights grant can be found |
||||
* in the file PATENTS. All contributing project authors may |
||||
* be found in the AUTHORS file in the root of the source tree. |
||||
* |
||||
* Based on code from the OggTheora software codec source code, |
||||
* Copyright (C) 2002-2010 The Xiph.Org Foundation and contributors. |
||||
*/ |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include "y4minput.h" |
||||
|
||||
static int y4m_parse_tags(y4m_input *_y4m,char *_tags){ |
||||
int got_w; |
||||
int got_h; |
||||
int got_fps; |
||||
int got_interlace; |
||||
int got_par; |
||||
int got_chroma; |
||||
char *p; |
||||
char *q; |
||||
got_w=got_h=got_fps=got_interlace=got_par=got_chroma=0; |
||||
for(p=_tags;;p=q){ |
||||
/*Skip any leading spaces.*/ |
||||
while(*p==' ')p++; |
||||
/*If that's all we have, stop.*/ |
||||
if(p[0]=='\0')break; |
||||
/*Find the end of this tag.*/ |
||||
for(q=p+1;*q!='\0'&&*q!=' ';q++); |
||||
/*Process the tag.*/ |
||||
switch(p[0]){ |
||||
case 'W':{ |
||||
if(sscanf(p+1,"%d",&_y4m->pic_w)!=1)return -1; |
||||
got_w=1; |
||||
}break; |
||||
case 'H':{ |
||||
if(sscanf(p+1,"%d",&_y4m->pic_h)!=1)return -1; |
||||
got_h=1; |
||||
}break; |
||||
case 'F':{ |
||||
if(sscanf(p+1,"%d:%d",&_y4m->fps_n,&_y4m->fps_d)!=2){ |
||||
return -1; |
||||
} |
||||
got_fps=1; |
||||
}break; |
||||
case 'I':{ |
||||
_y4m->interlace=p[1]; |
||||
got_interlace=1; |
||||
}break; |
||||
case 'A':{ |
||||
if(sscanf(p+1,"%d:%d",&_y4m->par_n,&_y4m->par_d)!=2){ |
||||
return -1; |
||||
} |
||||
got_par=1; |
||||
}break; |
||||
case 'C':{ |
||||
if(q-p>16)return -1; |
||||
memcpy(_y4m->chroma_type,p+1,q-p-1); |
||||
_y4m->chroma_type[q-p-1]='\0'; |
||||
got_chroma=1; |
||||
}break; |
||||
/*Ignore unknown tags.*/ |
||||
} |
||||
} |
||||
if(!got_w||!got_h||!got_fps)return -1; |
||||
if(!got_interlace)_y4m->interlace='?'; |
||||
if(!got_par)_y4m->par_n=_y4m->par_d=0; |
||||
/*Chroma-type is not specified in older files, e.g., those generated by
|
||||
mplayer.*/ |
||||
if(!got_chroma)strcpy(_y4m->chroma_type,"420"); |
||||
return 0; |
||||
} |
||||
|
||||
|
||||
|
||||
/*All anti-aliasing filters in the following conversion functions are based on
|
||||
one of two window functions: |
||||
The 6-tap Lanczos window (for down-sampling and shifts): |
||||
sinc(\pi*t)*sinc(\pi*t/3), |t|<3 (sinc(t)==sin(t)/t) |
||||
0, |t|>=3 |
||||
The 4-tap Mitchell window (for up-sampling): |
||||
7|t|^3-12|t|^2+16/3, |t|<1 |
||||
-(7/3)|x|^3+12|x|^2-20|x|+32/3, |t|<2 |
||||
0, |t|>=2 |
||||
The number of taps is intentionally kept small to reduce computational |
||||
overhead and limit ringing. |
||||
|
||||
The taps from these filters are scaled so that their sum is 1, and the result |
||||
is scaled by 128 and rounded to integers to create a filter whose |
||||
intermediate values fit inside 16 bits. |
||||
Coefficients are rounded in such a way as to ensure their sum is still 128, |
||||
which is usually equivalent to normal rounding. |
||||
|
||||
Conversions which require both horizontal and vertical filtering could |
||||
have these steps pipelined, for less memory consumption and better cache |
||||
performance, but we do them separately for simplicity.*/ |
||||
|
||||
#define OC_MINI(_a,_b) ((_a)>(_b)?(_b):(_a)) |
||||
#define OC_MAXI(_a,_b) ((_a)<(_b)?(_b):(_a)) |
||||
#define OC_CLAMPI(_a,_b,_c) (OC_MAXI(_a,OC_MINI(_b,_c))) |
||||
|
||||
/*420jpeg chroma samples are sited like:
|
||||
Y-------Y-------Y-------Y------- |
||||
| | | | |
||||
| BR | | BR | |
||||
| | | | |
||||
Y-------Y-------Y-------Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
Y-------Y-------Y-------Y------- |
||||
| | | | |
||||
| BR | | BR | |
||||
| | | | |
||||
Y-------Y-------Y-------Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
|
||||
420mpeg2 chroma samples are sited like: |
||||
Y-------Y-------Y-------Y------- |
||||
| | | | |
||||
BR | BR | |
||||
| | | | |
||||
Y-------Y-------Y-------Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
Y-------Y-------Y-------Y------- |
||||
| | | | |
||||
BR | BR | |
||||
| | | | |
||||
Y-------Y-------Y-------Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
|
||||
We use a resampling filter to shift the site locations one quarter pixel (at |
||||
the chroma plane's resolution) to the right. |
||||
The 4:2:2 modes look exactly the same, except there are twice as many chroma |
||||
lines, and they are vertically co-sited with the luma samples in both the |
||||
mpeg2 and jpeg cases (thus requiring no vertical resampling).*/ |
||||
static void y4m_42xmpeg2_42xjpeg_helper(unsigned char *_dst, |
||||
const unsigned char *_src,int _c_w,int _c_h){ |
||||
int y; |
||||
int x; |
||||
for(y=0;y<_c_h;y++){ |
||||
/*Filter: [4 -17 114 35 -9 1]/128, derived from a 6-tap Lanczos
|
||||
window.*/ |
||||
for(x=0;x<OC_MINI(_c_w,2);x++){ |
||||
_dst[x]=(unsigned char)OC_CLAMPI(0,(4*_src[0]-17*_src[OC_MAXI(x-1,0)]+ |
||||
114*_src[x]+35*_src[OC_MINI(x+1,_c_w-1)]-9*_src[OC_MINI(x+2,_c_w-1)]+ |
||||
_src[OC_MINI(x+3,_c_w-1)]+64)>>7,255); |
||||
} |
||||
for(;x<_c_w-3;x++){ |
||||
_dst[x]=(unsigned char)OC_CLAMPI(0,(4*_src[x-2]-17*_src[x-1]+ |
||||
114*_src[x]+35*_src[x+1]-9*_src[x+2]+_src[x+3]+64)>>7,255); |
||||
} |
||||
for(;x<_c_w;x++){ |
||||
_dst[x]=(unsigned char)OC_CLAMPI(0,(4*_src[x-2]-17*_src[x-1]+ |
||||
114*_src[x]+35*_src[OC_MINI(x+1,_c_w-1)]-9*_src[OC_MINI(x+2,_c_w-1)]+ |
||||
_src[_c_w-1]+64)>>7,255); |
||||
} |
||||
_dst+=_c_w; |
||||
_src+=_c_w; |
||||
} |
||||
} |
||||
|
||||
/*Handles both 422 and 420mpeg2 to 422jpeg and 420jpeg, respectively.*/ |
||||
static void y4m_convert_42xmpeg2_42xjpeg(y4m_input *_y4m,unsigned char *_dst, |
||||
unsigned char *_aux){ |
||||
int c_w; |
||||
int c_h; |
||||
int c_sz; |
||||
int pli; |
||||
/*Skip past the luma data.*/ |
||||
_dst+=_y4m->pic_w*_y4m->pic_h; |
||||
/*Compute the size of each chroma plane.*/ |
||||
c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h; |
||||
c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v; |
||||
c_sz=c_w*c_h; |
||||
for(pli=1;pli<3;pli++){ |
||||
y4m_42xmpeg2_42xjpeg_helper(_dst,_aux,c_w,c_h); |
||||
_dst+=c_sz; |
||||
_aux+=c_sz; |
||||
} |
||||
} |
||||
|
||||
/*This format is only used for interlaced content, but is included for
|
||||
completeness. |
||||
|
||||
420jpeg chroma samples are sited like: |
||||
Y-------Y-------Y-------Y------- |
||||
| | | | |
||||
| BR | | BR | |
||||
| | | | |
||||
Y-------Y-------Y-------Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
Y-------Y-------Y-------Y------- |
||||
| | | | |
||||
| BR | | BR | |
||||
| | | | |
||||
Y-------Y-------Y-------Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
|
||||
420paldv chroma samples are sited like: |
||||
YR------Y-------YR------Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
YB------Y-------YB------Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
YR------Y-------YR------Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
YB------Y-------YB------Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
|
||||
We use a resampling filter to shift the site locations one quarter pixel (at |
||||
the chroma plane's resolution) to the right. |
||||
Then we use another filter to move the C_r location down one quarter pixel, |
||||
and the C_b location up one quarter pixel.*/ |
||||
static void y4m_convert_42xpaldv_42xjpeg(y4m_input *_y4m,unsigned char *_dst, |
||||
unsigned char *_aux){ |
||||
unsigned char *tmp; |
||||
int c_w; |
||||
int c_h; |
||||
int c_sz; |
||||
int pli; |
||||
int y; |
||||
int x; |
||||
/*Skip past the luma data.*/ |
||||
_dst+=_y4m->pic_w*_y4m->pic_h; |
||||
/*Compute the size of each chroma plane.*/ |
||||
c_w=(_y4m->pic_w+1)/2; |
||||
c_h=(_y4m->pic_h+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h; |
||||
c_sz=c_w*c_h; |
||||
tmp=_aux+2*c_sz; |
||||
for(pli=1;pli<3;pli++){ |
||||
/*First do the horizontal re-sampling.
|
||||
This is the same as the mpeg2 case, except that after the horizontal |
||||
case, we need to apply a second vertical filter.*/ |
||||
y4m_42xmpeg2_42xjpeg_helper(tmp,_aux,c_w,c_h); |
||||
_aux+=c_sz; |
||||
switch(pli){ |
||||
case 1:{ |
||||
/*Slide C_b up a quarter-pel.
|
||||
This is the same filter used above, but in the other order.*/ |
||||
for(x=0;x<c_w;x++){ |
||||
for(y=0;y<OC_MINI(c_h,3);y++){ |
||||
_dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(tmp[0] |
||||
-9*tmp[OC_MAXI(y-2,0)*c_w]+35*tmp[OC_MAXI(y-1,0)*c_w] |
||||
+114*tmp[y*c_w]-17*tmp[OC_MINI(y+1,c_h-1)*c_w] |
||||
+4*tmp[OC_MINI(y+2,c_h-1)*c_w]+64)>>7,255); |
||||
} |
||||
for(;y<c_h-2;y++){ |
||||
_dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(tmp[(y-3)*c_w] |
||||
-9*tmp[(y-2)*c_w]+35*tmp[(y-1)*c_w]+114*tmp[y*c_w] |
||||
-17*tmp[(y+1)*c_w]+4*tmp[(y+2)*c_w]+64)>>7,255); |
||||
} |
||||
for(;y<c_h;y++){ |
||||
_dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(tmp[(y-3)*c_w] |
||||
-9*tmp[(y-2)*c_w]+35*tmp[(y-1)*c_w]+114*tmp[y*c_w] |
||||
-17*tmp[OC_MINI(y+1,c_h-1)*c_w]+4*tmp[(c_h-1)*c_w]+64)>>7,255); |
||||
} |
||||
_dst++; |
||||
tmp++; |
||||
} |
||||
_dst+=c_sz-c_w; |
||||
tmp-=c_w; |
||||
}break; |
||||
case 2:{ |
||||
/*Slide C_r down a quarter-pel.
|
||||
This is the same as the horizontal filter.*/ |
||||
for(x=0;x<c_w;x++){ |
||||
for(y=0;y<OC_MINI(c_h,2);y++){ |
||||
_dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(4*tmp[0] |
||||
-17*tmp[OC_MAXI(y-1,0)*c_w]+114*tmp[y*c_w] |
||||
+35*tmp[OC_MINI(y+1,c_h-1)*c_w]-9*tmp[OC_MINI(y+2,c_h-1)*c_w] |
||||
+tmp[OC_MINI(y+3,c_h-1)*c_w]+64)>>7,255); |
||||
} |
||||
for(;y<c_h-3;y++){ |
||||
_dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(4*tmp[(y-2)*c_w] |
||||
-17*tmp[(y-1)*c_w]+114*tmp[y*c_w]+35*tmp[(y+1)*c_w] |
||||
-9*tmp[(y+2)*c_w]+tmp[(y+3)*c_w]+64)>>7,255); |
||||
} |
||||
for(;y<c_h;y++){ |
||||
_dst[y*c_w]=(unsigned char)OC_CLAMPI(0,(4*tmp[(y-2)*c_w] |
||||
-17*tmp[(y-1)*c_w]+114*tmp[y*c_w]+35*tmp[OC_MINI(y+1,c_h-1)*c_w] |
||||
-9*tmp[OC_MINI(y+2,c_h-1)*c_w]+tmp[(c_h-1)*c_w]+64)>>7,255); |
||||
} |
||||
_dst++; |
||||
tmp++; |
||||
} |
||||
}break; |
||||
} |
||||
/*For actual interlaced material, this would have to be done separately on
|
||||
each field, and the shift amounts would be different. |
||||
C_r moves down 1/8, C_b up 3/8 in the top field, and C_r moves down 3/8, |
||||
C_b up 1/8 in the bottom field. |
||||
The corresponding filters would be: |
||||
Down 1/8 (reverse order for up): [3 -11 125 15 -4 0]/128 |
||||
Down 3/8 (reverse order for up): [4 -19 98 56 -13 2]/128*/ |
||||
} |
||||
} |
||||
|
||||
/*Perform vertical filtering to reduce a single plane from 4:2:2 to 4:2:0.
|
||||
This is used as a helper by several converation routines.*/ |
||||
static void y4m_422jpeg_420jpeg_helper(unsigned char *_dst, |
||||
const unsigned char *_src,int _c_w,int _c_h){ |
||||
int y; |
||||
int x; |
||||
/*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/ |
||||
for(x=0;x<_c_w;x++){ |
||||
for(y=0;y<OC_MINI(_c_h,2);y+=2){ |
||||
_dst[(y>>1)*_c_w]=OC_CLAMPI(0,(64*_src[0] |
||||
+78*_src[OC_MINI(1,_c_h-1)*_c_w] |
||||
-17*_src[OC_MINI(2,_c_h-1)*_c_w] |
||||
+3*_src[OC_MINI(3,_c_h-1)*_c_w]+64)>>7,255); |
||||
} |
||||
for(;y<_c_h-3;y+=2){ |
||||
_dst[(y>>1)*_c_w]=OC_CLAMPI(0,(3*(_src[(y-2)*_c_w]+_src[(y+3)*_c_w]) |
||||
-17*(_src[(y-1)*_c_w]+_src[(y+2)*_c_w]) |
||||
+78*(_src[y*_c_w]+_src[(y+1)*_c_w])+64)>>7,255); |
||||
} |
||||
for(;y<_c_h;y+=2){ |
||||
_dst[(y>>1)*_c_w]=OC_CLAMPI(0,(3*(_src[(y-2)*_c_w] |
||||
+_src[(_c_h-1)*_c_w])-17*(_src[(y-1)*_c_w] |
||||
+_src[OC_MINI(y+2,_c_h-1)*_c_w]) |
||||
+78*(_src[y*_c_w]+_src[OC_MINI(y+1,_c_h-1)*_c_w])+64)>>7,255); |
||||
} |
||||
_src++; |
||||
_dst++; |
||||
} |
||||
} |
||||
|
||||
/*420jpeg chroma samples are sited like:
|
||||
Y-------Y-------Y-------Y------- |
||||
| | | | |
||||
| BR | | BR | |
||||
| | | | |
||||
Y-------Y-------Y-------Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
Y-------Y-------Y-------Y------- |
||||
| | | | |
||||
| BR | | BR | |
||||
| | | | |
||||
Y-------Y-------Y-------Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
|
||||
422jpeg chroma samples are sited like: |
||||
Y---BR--Y-------Y---BR--Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
Y---BR--Y-------Y---BR--Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
Y---BR--Y-------Y---BR--Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
Y---BR--Y-------Y---BR--Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
|
||||
We use a resampling filter to decimate the chroma planes by two in the |
||||
vertical direction.*/ |
||||
static void y4m_convert_422jpeg_420jpeg(y4m_input *_y4m,unsigned char *_dst, |
||||
unsigned char *_aux){ |
||||
int c_w; |
||||
int c_h; |
||||
int c_sz; |
||||
int dst_c_w; |
||||
int dst_c_h; |
||||
int dst_c_sz; |
||||
int pli; |
||||
/*Skip past the luma data.*/ |
||||
_dst+=_y4m->pic_w*_y4m->pic_h; |
||||
/*Compute the size of each chroma plane.*/ |
||||
c_w=(_y4m->pic_w+_y4m->src_c_dec_h-1)/_y4m->src_c_dec_h; |
||||
c_h=_y4m->pic_h; |
||||
dst_c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h; |
||||
dst_c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v; |
||||
c_sz=c_w*c_h; |
||||
dst_c_sz=dst_c_w*dst_c_h; |
||||
for(pli=1;pli<3;pli++){ |
||||
y4m_422jpeg_420jpeg_helper(_dst,_aux,c_w,c_h); |
||||
_aux+=c_sz; |
||||
_dst+=dst_c_sz; |
||||
} |
||||
} |
||||
|
||||
/*420jpeg chroma samples are sited like:
|
||||
Y-------Y-------Y-------Y------- |
||||
| | | | |
||||
| BR | | BR | |
||||
| | | | |
||||
Y-------Y-------Y-------Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
Y-------Y-------Y-------Y------- |
||||
| | | | |
||||
| BR | | BR | |
||||
| | | | |
||||
Y-------Y-------Y-------Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
|
||||
422 chroma samples are sited like: |
||||
YBR-----Y-------YBR-----Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
YBR-----Y-------YBR-----Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
YBR-----Y-------YBR-----Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
YBR-----Y-------YBR-----Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
|
||||
We use a resampling filter to shift the original site locations one quarter |
||||
pixel (at the original chroma resolution) to the right. |
||||
Then we use a second resampling filter to decimate the chroma planes by two |
||||
in the vertical direction.*/ |
||||
static void y4m_convert_422_420jpeg(y4m_input *_y4m,unsigned char *_dst, |
||||
unsigned char *_aux){ |
||||
unsigned char *tmp; |
||||
int c_w; |
||||
int c_h; |
||||
int c_sz; |
||||
int dst_c_h; |
||||
int dst_c_sz; |
||||
int pli; |
||||
/*Skip past the luma data.*/ |
||||
_dst+=_y4m->pic_w*_y4m->pic_h; |
||||
/*Compute the size of each chroma plane.*/ |
||||
c_w=(_y4m->pic_w+_y4m->src_c_dec_h-1)/_y4m->src_c_dec_h; |
||||
c_h=_y4m->pic_h; |
||||
dst_c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v; |
||||
c_sz=c_w*c_h; |
||||
dst_c_sz=c_w*dst_c_h; |
||||
tmp=_aux+2*c_sz; |
||||
for(pli=1;pli<3;pli++){ |
||||
/*In reality, the horizontal and vertical steps could be pipelined, for
|
||||
less memory consumption and better cache performance, but we do them |
||||
separately for simplicity.*/ |
||||
/*First do horizontal filtering (convert to 422jpeg)*/ |
||||
y4m_42xmpeg2_42xjpeg_helper(tmp,_aux,c_w,c_h); |
||||
/*Now do the vertical filtering.*/ |
||||
y4m_422jpeg_420jpeg_helper(_dst,tmp,c_w,c_h); |
||||
_aux+=c_sz; |
||||
_dst+=dst_c_sz; |
||||
} |
||||
} |
||||
|
||||
/*420jpeg chroma samples are sited like:
|
||||
Y-------Y-------Y-------Y------- |
||||
| | | | |
||||
| BR | | BR | |
||||
| | | | |
||||
Y-------Y-------Y-------Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
Y-------Y-------Y-------Y------- |
||||
| | | | |
||||
| BR | | BR | |
||||
| | | | |
||||
Y-------Y-------Y-------Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
|
||||
411 chroma samples are sited like: |
||||
YBR-----Y-------Y-------Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
YBR-----Y-------Y-------Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
YBR-----Y-------Y-------Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
YBR-----Y-------Y-------Y------- |
||||
| | | | |
||||
| | | | |
||||
| | | | |
||||
|
||||
We use a filter to resample at site locations one eighth pixel (at the source |
||||
chroma plane's horizontal resolution) and five eighths of a pixel to the |
||||
right. |
||||
Then we use another filter to decimate the planes by 2 in the vertical |
||||
direction.*/ |
||||
static void y4m_convert_411_420jpeg(y4m_input *_y4m,unsigned char *_dst, |
||||
unsigned char *_aux){ |
||||
unsigned char *tmp; |
||||
int c_w; |
||||
int c_h; |
||||
int c_sz; |
||||
int dst_c_w; |
||||
int dst_c_h; |
||||
int dst_c_sz; |
||||
int tmp_sz; |
||||
int pli; |
||||
int y; |
||||
int x; |
||||
/*Skip past the luma data.*/ |
||||
_dst+=_y4m->pic_w*_y4m->pic_h; |
||||
/*Compute the size of each chroma plane.*/ |
||||
c_w=(_y4m->pic_w+_y4m->src_c_dec_h-1)/_y4m->src_c_dec_h; |
||||
c_h=_y4m->pic_h; |
||||
dst_c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h; |
||||
dst_c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v; |
||||
c_sz=c_w*c_h; |
||||
dst_c_sz=dst_c_w*dst_c_h; |
||||
tmp_sz=dst_c_w*c_h; |
||||
tmp=_aux+2*c_sz; |
||||
for(pli=1;pli<3;pli++){ |
||||
/*In reality, the horizontal and vertical steps could be pipelined, for
|
||||
less memory consumption and better cache performance, but we do them |
||||
separately for simplicity.*/ |
||||
/*First do horizontal filtering (convert to 422jpeg)*/ |
||||
for(y=0;y<c_h;y++){ |
||||
/*Filters: [1 110 18 -1]/128 and [-3 50 86 -5]/128, both derived from a
|
||||
4-tap Mitchell window.*/ |
||||
for(x=0;x<OC_MINI(c_w,1);x++){ |
||||
tmp[x<<1]=(unsigned char)OC_CLAMPI(0,(111*_aux[0] |
||||
+18*_aux[OC_MINI(1,c_w-1)]-_aux[OC_MINI(2,c_w-1)]+64)>>7,255); |
||||
tmp[x<<1|1]=(unsigned char)OC_CLAMPI(0,(47*_aux[0] |
||||
+86*_aux[OC_MINI(1,c_w-1)]-5*_aux[OC_MINI(2,c_w-1)]+64)>>7,255); |
||||
} |
||||
for(;x<c_w-2;x++){ |
||||
tmp[x<<1]=(unsigned char)OC_CLAMPI(0,(_aux[x-1]+110*_aux[x] |
||||
+18*_aux[x+1]-_aux[x+2]+64)>>7,255); |
||||
tmp[x<<1|1]=(unsigned char)OC_CLAMPI(0,(-3*_aux[x-1]+50*_aux[x] |
||||
+86*_aux[x+1]-5*_aux[x+2]+64)>>7,255); |
||||
} |
||||
for(;x<c_w;x++){ |
||||
tmp[x<<1]=(unsigned char)OC_CLAMPI(0,(_aux[x-1]+110*_aux[x] |
||||
+18*_aux[OC_MINI(x+1,c_w-1)]-_aux[c_w-1]+64)>>7,255); |
||||
if((x<<1|1)<dst_c_w){ |
||||
tmp[x<<1|1]=(unsigned char)OC_CLAMPI(0,(-3*_aux[x-1]+50*_aux[x] |
||||
+86*_aux[OC_MINI(x+1,c_w-1)]-5*_aux[c_w-1]+64)>>7,255); |
||||
} |
||||
} |
||||
tmp+=dst_c_w; |
||||
_aux+=c_w; |
||||
} |
||||
tmp-=tmp_sz; |
||||
/*Now do the vertical filtering.*/ |
||||
y4m_422jpeg_420jpeg_helper(_dst,tmp,dst_c_w,c_h); |
||||
_dst+=dst_c_sz; |
||||
} |
||||
} |
||||
|
||||
/*Convert 444 to 420jpeg.*/ |
||||
static void y4m_convert_444_420jpeg(y4m_input *_y4m,unsigned char *_dst, |
||||
unsigned char *_aux){ |
||||
unsigned char *tmp; |
||||
int c_w; |
||||
int c_h; |
||||
int c_sz; |
||||
int dst_c_w; |
||||
int dst_c_h; |
||||
int dst_c_sz; |
||||
int tmp_sz; |
||||
int pli; |
||||
int y; |
||||
int x; |
||||
/*Skip past the luma data.*/ |
||||
_dst+=_y4m->pic_w*_y4m->pic_h; |
||||
/*Compute the size of each chroma plane.*/ |
||||
c_w=(_y4m->pic_w+_y4m->src_c_dec_h-1)/_y4m->src_c_dec_h; |
||||
c_h=_y4m->pic_h; |
||||
dst_c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h; |
||||
dst_c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v; |
||||
c_sz=c_w*c_h; |
||||
dst_c_sz=dst_c_w*dst_c_h; |
||||
tmp_sz=dst_c_w*c_h; |
||||
tmp=_aux+2*c_sz; |
||||
for(pli=1;pli<3;pli++){ |
||||
/*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/ |
||||
for(y=0;y<c_h;y++){ |
||||
for(x=0;x<OC_MINI(c_w,2);x+=2){ |
||||
tmp[x>>1]=OC_CLAMPI(0,(64*_aux[0]+78*_aux[OC_MINI(1,c_w-1)] |
||||
-17*_aux[OC_MINI(2,c_w-1)] |
||||
+3*_aux[OC_MINI(3,c_w-1)]+64)>>7,255); |
||||
} |
||||
for(;x<c_w-3;x+=2){ |
||||
tmp[x>>1]=OC_CLAMPI(0,(3*(_aux[x-2]+_aux[x+3]) |
||||
-17*(_aux[x-1]+_aux[x+2])+78*(_aux[x]+_aux[x+1])+64)>>7,255); |
||||
} |
||||
for(;x<c_w;x+=2){ |
||||
tmp[x>>1]=OC_CLAMPI(0,(3*(_aux[x-2]+_aux[c_w-1])- |
||||
17*(_aux[x-1]+_aux[OC_MINI(x+2,c_w-1)])+ |
||||
78*(_aux[x]+_aux[OC_MINI(x+1,c_w-1)])+64)>>7,255); |
||||
} |
||||
tmp+=dst_c_w; |
||||
_aux+=c_w; |
||||
} |
||||
tmp-=tmp_sz; |
||||
/*Now do the vertical filtering.*/ |
||||
y4m_422jpeg_420jpeg_helper(_dst,tmp,dst_c_w,c_h); |
||||
_dst+=dst_c_sz; |
||||
} |
||||
} |
||||
|
||||
/*The image is padded with empty chroma components at 4:2:0.*/ |
||||
static void y4m_convert_mono_420jpeg(y4m_input *_y4m,unsigned char *_dst, |
||||
unsigned char *_aux){ |
||||
int c_sz; |
||||
_dst+=_y4m->pic_w*_y4m->pic_h; |
||||
c_sz=((_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h)* |
||||
((_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v); |
||||
memset(_dst,128,c_sz*2); |
||||
} |
||||
|
||||
/*No conversion function needed.*/ |
||||
static void y4m_convert_null(y4m_input *_y4m,unsigned char *_dst, |
||||
unsigned char *_aux){ |
||||
} |
||||
|
||||
int y4m_input_open(y4m_input *_y4m,FILE *_fin,char *_skip,int _nskip){ |
||||
char buffer[80]; |
||||
int ret; |
||||
int i; |
||||
/*Read until newline, or 80 cols, whichever happens first.*/ |
||||
for(i=0;i<79;i++){ |
||||
if(_nskip>0){ |
||||
buffer[i]=*_skip++; |
||||
_nskip--; |
||||
} |
||||
else{ |
||||
ret=fread(buffer+i,1,1,_fin); |
||||
if(ret<1)return -1; |
||||
} |
||||
if(buffer[i]=='\n')break; |
||||
} |
||||
/*We skipped too much header data.*/ |
||||
if(_nskip>0)return -1; |
||||
if(i==79){ |
||||
fprintf(stderr,"Error parsing header; not a YUV2MPEG2 file?\n"); |
||||
return -1; |
||||
} |
||||
buffer[i]='\0'; |
||||
if(memcmp(buffer,"YUV4MPEG",8)){ |
||||
fprintf(stderr,"Incomplete magic for YUV4MPEG file.\n"); |
||||
return -1; |
||||
} |
||||
if(buffer[8]!='2'){ |
||||
fprintf(stderr,"Incorrect YUV input file version; YUV4MPEG2 required.\n"); |
||||
} |
||||
ret=y4m_parse_tags(_y4m,buffer+5); |
||||
if(ret<0){ |
||||
fprintf(stderr,"Error parsing YUV4MPEG2 header.\n"); |
||||
return ret; |
||||
} |
||||
if(_y4m->interlace=='?'){ |
||||
fprintf(stderr,"Warning: Input video interlacing format unknown; " |
||||
"assuming progressive scan.\n"); |
||||
} |
||||
else if(_y4m->interlace!='p'){ |
||||
fprintf(stderr,"Input video is interlaced; " |
||||
"Only progressive scan handled.\n"); |
||||
return -1; |
||||
} |
||||
if(strcmp(_y4m->chroma_type,"420")==0|| |
||||
strcmp(_y4m->chroma_type,"420jpeg")==0){ |
||||
_y4m->src_c_dec_h=_y4m->dst_c_dec_h=_y4m->src_c_dec_v=_y4m->dst_c_dec_v=2; |
||||
_y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h |
||||
+2*((_y4m->pic_w+1)/2)*((_y4m->pic_h+1)/2); |
||||
/*Natively supported: no conversion required.*/ |
||||
_y4m->aux_buf_sz=_y4m->aux_buf_read_sz=0; |
||||
_y4m->convert=y4m_convert_null; |
||||
} |
||||
else if(strcmp(_y4m->chroma_type,"420mpeg2")==0){ |
||||
_y4m->src_c_dec_h=_y4m->dst_c_dec_h=_y4m->src_c_dec_v=_y4m->dst_c_dec_v=2; |
||||
_y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h; |
||||
/*Chroma filter required: read into the aux buf first.*/ |
||||
_y4m->aux_buf_sz=_y4m->aux_buf_read_sz= |
||||
2*((_y4m->pic_w+1)/2)*((_y4m->pic_h+1)/2); |
||||
_y4m->convert=y4m_convert_42xmpeg2_42xjpeg; |
||||
} |
||||
else if(strcmp(_y4m->chroma_type,"420paldv")==0){ |
||||
_y4m->src_c_dec_h=_y4m->dst_c_dec_h=_y4m->src_c_dec_v=_y4m->dst_c_dec_v=2; |
||||
_y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h; |
||||
/*Chroma filter required: read into the aux buf first.
|
||||
We need to make two filter passes, so we need some extra space in the |
||||
aux buffer.*/ |
||||
_y4m->aux_buf_sz=3*((_y4m->pic_w+1)/2)*((_y4m->pic_h+1)/2); |
||||
_y4m->aux_buf_read_sz=2*((_y4m->pic_w+1)/2)*((_y4m->pic_h+1)/2); |
||||
_y4m->convert=y4m_convert_42xpaldv_42xjpeg; |
||||
} |
||||
else if(strcmp(_y4m->chroma_type,"422jpeg")==0){ |
||||
_y4m->src_c_dec_h=_y4m->dst_c_dec_h=2; |
||||
_y4m->src_c_dec_v=1; |
||||
_y4m->dst_c_dec_v=2; |
||||
_y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h; |
||||
/*Chroma filter required: read into the aux buf first.*/ |
||||
_y4m->aux_buf_sz=_y4m->aux_buf_read_sz=2*((_y4m->pic_w+1)/2)*_y4m->pic_h; |
||||
_y4m->convert=y4m_convert_422jpeg_420jpeg; |
||||
} |
||||
else if(strcmp(_y4m->chroma_type,"422")==0){ |
||||
_y4m->src_c_dec_h=_y4m->dst_c_dec_h=2; |
||||
_y4m->src_c_dec_v=1; |
||||
_y4m->dst_c_dec_v=2; |
||||
_y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h; |
||||
/*Chroma filter required: read into the aux buf first.
|
||||
We need to make two filter passes, so we need some extra space in the |
||||
aux buffer.*/ |
||||
_y4m->aux_buf_read_sz=2*((_y4m->pic_w+1)/2)*_y4m->pic_h; |
||||
_y4m->aux_buf_sz=_y4m->aux_buf_read_sz+((_y4m->pic_w+1)/2)*_y4m->pic_h; |
||||
_y4m->convert=y4m_convert_422_420jpeg; |
||||
} |
||||
else if(strcmp(_y4m->chroma_type,"411")==0){ |
||||
_y4m->src_c_dec_h=4; |
||||
_y4m->dst_c_dec_h=2; |
||||
_y4m->src_c_dec_v=1; |
||||
_y4m->dst_c_dec_v=2; |
||||
_y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h; |
||||
/*Chroma filter required: read into the aux buf first.
|
||||
We need to make two filter passes, so we need some extra space in the |
||||
aux buffer.*/ |
||||
_y4m->aux_buf_read_sz=2*((_y4m->pic_w+3)/4)*_y4m->pic_h; |
||||
_y4m->aux_buf_sz=_y4m->aux_buf_read_sz+((_y4m->pic_w+1)/2)*_y4m->pic_h; |
||||
_y4m->convert=y4m_convert_411_420jpeg; |
||||
} |
||||
else if(strcmp(_y4m->chroma_type,"444")==0){ |
||||
_y4m->src_c_dec_h=1; |
||||
_y4m->dst_c_dec_h=2; |
||||
_y4m->src_c_dec_v=1; |
||||
_y4m->dst_c_dec_v=2; |
||||
_y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h; |
||||
/*Chroma filter required: read into the aux buf first.
|
||||
We need to make two filter passes, so we need some extra space in the |
||||
aux buffer.*/ |
||||
_y4m->aux_buf_read_sz=2*_y4m->pic_w*_y4m->pic_h; |
||||
_y4m->aux_buf_sz=_y4m->aux_buf_read_sz+((_y4m->pic_w+1)/2)*_y4m->pic_h; |
||||
_y4m->convert=y4m_convert_444_420jpeg; |
||||
} |
||||
else if(strcmp(_y4m->chroma_type,"444alpha")==0){ |
||||
_y4m->src_c_dec_h=1; |
||||
_y4m->dst_c_dec_h=2; |
||||
_y4m->src_c_dec_v=1; |
||||
_y4m->dst_c_dec_v=2; |
||||
_y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h; |
||||
/*Chroma filter required: read into the aux buf first.
|
||||
We need to make two filter passes, so we need some extra space in the |
||||
aux buffer. |
||||
The extra plane also gets read into the aux buf. |
||||
It will be discarded.*/ |
||||
_y4m->aux_buf_sz=_y4m->aux_buf_read_sz=3*_y4m->pic_w*_y4m->pic_h; |
||||
_y4m->convert=y4m_convert_444_420jpeg; |
||||
} |
||||
else if(strcmp(_y4m->chroma_type,"mono")==0){ |
||||
_y4m->src_c_dec_h=_y4m->src_c_dec_v=0; |
||||
_y4m->dst_c_dec_h=_y4m->dst_c_dec_v=2; |
||||
_y4m->dst_buf_read_sz=_y4m->pic_w*_y4m->pic_h; |
||||
/*No extra space required, but we need to clear the chroma planes.*/ |
||||
_y4m->aux_buf_sz=_y4m->aux_buf_read_sz=0; |
||||
_y4m->convert=y4m_convert_mono_420jpeg; |
||||
} |
||||
else{ |
||||
fprintf(stderr,"Unknown chroma sampling type: %s\n",_y4m->chroma_type); |
||||
return -1; |
||||
} |
||||
/*The size of the final frame buffers is always computed from the
|
||||
destination chroma decimation type.*/ |
||||
_y4m->dst_buf_sz=_y4m->pic_w*_y4m->pic_h |
||||
+2*((_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h)* |
||||
((_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v); |
||||
_y4m->dst_buf=(unsigned char *)malloc(_y4m->dst_buf_sz); |
||||
_y4m->aux_buf=(unsigned char *)malloc(_y4m->aux_buf_sz); |
||||
return 0; |
||||
} |
||||
|
||||
void y4m_input_close(y4m_input *_y4m){ |
||||
free(_y4m->dst_buf); |
||||
free(_y4m->aux_buf); |
||||
} |
||||
|
||||
int y4m_input_fetch_frame(y4m_input *_y4m,FILE *_fin,vpx_image_t *_img){ |
||||
char frame[6]; |
||||
int pic_sz; |
||||
int c_w; |
||||
int c_h; |
||||
int c_sz; |
||||
int ret; |
||||
/*Read and skip the frame header.*/ |
||||
ret=fread(frame,1,6,_fin); |
||||
if(ret<6)return 0; |
||||
if(memcmp(frame,"FRAME",5)){ |
||||
fprintf(stderr,"Loss of framing in Y4M input data\n"); |
||||
return -1; |
||||
} |
||||
if(frame[5]!='\n'){ |
||||
char c; |
||||
int j; |
||||
for(j=0;j<79&&fread(&c,1,1,_fin)&&c!='\n';j++); |
||||
if(j==79){ |
||||
fprintf(stderr,"Error parsing Y4M frame header\n"); |
||||
return -1; |
||||
} |
||||
} |
||||
/*Read the frame data that needs no conversion.*/ |
||||
if(fread(_y4m->dst_buf,1,_y4m->dst_buf_read_sz,_fin)!=_y4m->dst_buf_read_sz){ |
||||
fprintf(stderr,"Error reading Y4M frame data.\n"); |
||||
return -1; |
||||
} |
||||
/*Read the frame data that does need conversion.*/ |
||||
if(fread(_y4m->aux_buf,1,_y4m->aux_buf_read_sz,_fin)!=_y4m->aux_buf_read_sz){ |
||||
fprintf(stderr,"Error reading Y4M frame data.\n"); |
||||
return -1; |
||||
} |
||||
/*Now convert the just read frame.*/ |
||||
(*_y4m->convert)(_y4m,_y4m->dst_buf,_y4m->aux_buf); |
||||
/*Fill in the frame buffer pointers.
|
||||
We don't use vpx_img_wrap() because it forces padding for odd picture |
||||
sizes, which would require a separate fread call for every row.*/ |
||||
memset(_img,0,sizeof(*_img)); |
||||
/*Y4M has the planes in Y'CbCr order, which libvpx calls Y, U, and V.*/ |
||||
_img->fmt=IMG_FMT_I420; |
||||
_img->w=_img->d_w=_y4m->pic_w; |
||||
_img->h=_img->d_h=_y4m->pic_h; |
||||
/*This is hard-coded to 4:2:0 for now, as that's all VP8 supports.*/ |
||||
_img->x_chroma_shift=1; |
||||
_img->y_chroma_shift=1; |
||||
_img->bps=12; |
||||
/*Set up the buffer pointers.*/ |
||||
pic_sz=_y4m->pic_w*_y4m->pic_h; |
||||
c_w=(_y4m->pic_w+_y4m->dst_c_dec_h-1)/_y4m->dst_c_dec_h; |
||||
c_h=(_y4m->pic_h+_y4m->dst_c_dec_v-1)/_y4m->dst_c_dec_v; |
||||
c_sz=c_w*c_h; |
||||
_img->stride[PLANE_Y]=_y4m->pic_w; |
||||
_img->stride[PLANE_U]=_img->stride[PLANE_V]=c_w; |
||||
_img->planes[PLANE_Y]=_y4m->dst_buf; |
||||
_img->planes[PLANE_U]=_y4m->dst_buf+pic_sz; |
||||
_img->planes[PLANE_V]=_y4m->dst_buf+pic_sz+c_sz; |
||||
return 1; |
||||
} |
@ -0,0 +1,60 @@ |
||||
/*
|
||||
* Copyright (c) 2010 The WebM project authors. All Rights Reserved. |
||||
* |
||||
* Use of this source code is governed by a BSD-style license |
||||
* that can be found in the LICENSE file in the root of the source |
||||
* tree. An additional intellectual property rights grant can be found |
||||
* in the file PATENTS. All contributing project authors may |
||||
* be found in the AUTHORS file in the root of the source tree. |
||||
* |
||||
* Based on code from the OggTheora software codec source code, |
||||
* Copyright (C) 2002-2010 The Xiph.Org Foundation and contributors. |
||||
*/ |
||||
#if !defined(_y4minput_H) |
||||
# define _y4minput_H (1) |
||||
# include <stdio.h> |
||||
# include "vpx/vpx_image.h" |
||||
|
||||
|
||||
|
||||
typedef struct y4m_input y4m_input; |
||||
|
||||
|
||||
|
||||
/*The function used to perform chroma conversion.*/ |
||||
typedef void (*y4m_convert_func)(y4m_input *_y4m, |
||||
unsigned char *_dst,unsigned char *_src); |
||||
|
||||
|
||||
|
||||
struct y4m_input{ |
||||
int pic_w; |
||||
int pic_h; |
||||
int fps_n; |
||||
int fps_d; |
||||
int par_n; |
||||
int par_d; |
||||
char interlace; |
||||
int src_c_dec_h; |
||||
int src_c_dec_v; |
||||
int dst_c_dec_h; |
||||
int dst_c_dec_v; |
||||
char chroma_type[16]; |
||||
/*The size of each converted frame buffer.*/ |
||||
size_t dst_buf_sz; |
||||
/*The amount to read directly into the converted frame buffer.*/ |
||||
size_t dst_buf_read_sz; |
||||
/*The size of the auxilliary buffer.*/ |
||||
size_t aux_buf_sz; |
||||
/*The amount to read into the auxilliary buffer.*/ |
||||
size_t aux_buf_read_sz; |
||||
y4m_convert_func convert; |
||||
unsigned char *dst_buf; |
||||
unsigned char *aux_buf; |
||||
}; |
||||
|
||||
int y4m_input_open(y4m_input *_y4m,FILE *_fin,char *_skip,int _nskip); |
||||
void y4m_input_close(y4m_input *_y4m); |
||||
int y4m_input_fetch_frame(y4m_input *_y4m,FILE *_fin,vpx_image_t *img); |
||||
|
||||
#endif |
Loading…
Reference in new issue