mirror of
https://gitlab.freedesktop.org/wayland/weston
synced 2024-10-06 18:28:04 +00:00
Import vpxenc from libvpx as a starting point
This commit is contained in:
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
|
||||
|
|
|
@ -27,6 +27,8 @@ AC_SUBST(DLOPEN_LIBS)
|
|||
PKG_CHECK_MODULES(COMPOSITOR,
|
||||
[wayland-server egl >= 7.10 glesv2 xkbcommon pixman-1])
|
||||
|
||||
PKG_CHECK_MODULES(WCAP, [cairo vpx])
|
||||
|
||||
AC_CHECK_PROG(RSVG_CONVERT, rsvg-convert, rsvg-convert)
|
||||
AM_CONDITIONAL(HAVE_RSVG_CONVERT, test -n "$RSVG_CONVERT")
|
||||
|
||||
|
@ -196,6 +198,7 @@ AC_CONFIG_FILES([Makefile
|
|||
src/Makefile
|
||||
src/xwayland/Makefile
|
||||
clients/Makefile
|
||||
wcap-decode/Makefile
|
||||
data/Makefile
|
||||
protocol/Makefile
|
||||
tests/Makefile])
|
||||
|
|
231
wcap-decode/EbmlIDs.h
Normal file
231
wcap-decode/EbmlIDs.h
Normal file
|
@ -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
|
171
wcap-decode/EbmlWriter.c
Normal file
171
wcap-decode/EbmlWriter.c
Normal file
|
@ -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
|
38
wcap-decode/EbmlWriter.h
Normal file
38
wcap-decode/EbmlWriter.h
Normal file
|
@ -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
|
265
wcap-decode/args.c
Normal file
265
wcap-decode/args.c
Normal file
|
@ -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);
|
||||
}
|
54
wcap-decode/args.h
Normal file
54
wcap-decode/args.h
Normal file
|
@ -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
|
234
wcap-decode/mem_ops.h
Normal file
234
wcap-decode/mem_ops.h
Normal file
|
@ -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;
|
||||
}
|
157
wcap-decode/mem_ops_aligned.h
Normal file
157
wcap-decode/mem_ops_aligned.h
Normal file
|
@ -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
|
30
wcap-decode/tools_common.c
Normal file
30
wcap-decode/tools_common.c
Normal file
|
@ -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;
|
||||
}
|
16
wcap-decode/tools_common.h
Normal file
16
wcap-decode/tools_common.h
Normal file
|
@ -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
|
120
wcap-decode/vpx_timer.h
Normal file
120
wcap-decode/vpx_timer.h
Normal file
|
@ -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
|
2544
wcap-decode/vpxenc.c
Normal file
2544
wcap-decode/vpxenc.c
Normal file
File diff suppressed because it is too large
Load diff
218
wcap-decode/wcap-decode.c
Normal file
218
wcap-decode/wcap-decode.c
Normal file
|
@ -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);
|
||||
}
|
871
wcap-decode/y4minput.c
Normal file
871
wcap-decode/y4minput.c
Normal file
|
@ -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;
|
||||
}
|
60
wcap-decode/y4minput.h
Normal file
60
wcap-decode/y4minput.h
Normal file
|
@ -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 a new issue