Instead of having a custom fork of the vpxenc tool in weston, we can just dump raw YUV data in the YUV4MPEG2 format and feed that into the upstream vpxenc. This also works with theora_encoder and probably many other encoders.dev
parent
94de680439
commit
c12efd0aa7
@ -1,34 +0,0 @@ |
||||
The wcap-decode tool is based on the vpxenc tool from libvpx which is |
||||
under the following license: |
||||
|
||||
Copyright (c) 2010, The WebM Project authors. All rights reserved. |
||||
|
||||
Redistribution and use in source and binary forms, with or without |
||||
modification, are permitted provided that the following conditions are |
||||
met: |
||||
|
||||
* Redistributions of source code must retain the above copyright |
||||
notice, this list of conditions and the following disclaimer. |
||||
|
||||
* Redistributions in binary form must reproduce the above copyright |
||||
notice, this list of conditions and the following disclaimer in |
||||
the documentation and/or other materials provided with the |
||||
distribution. |
||||
|
||||
* Neither the name of Google, nor the WebM Project, nor the names |
||||
of its contributors may be used to endorse or promote products |
||||
derived from this software without specific prior written |
||||
permission. |
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
|
@ -1,231 +0,0 @@ |
||||
// 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 |
@ -1,171 +0,0 @@ |
||||
// 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
|
@ -1,38 +0,0 @@ |
||||
#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 |
@ -1,265 +0,0 @@ |
||||
/*
|
||||
* 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); |
||||
} |
@ -1,54 +0,0 @@ |
||||
/*
|
||||
* 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,240 @@ |
||||
/*
|
||||
* 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> |
||||
|
||||
#include "wcap-decode.h" |
||||
|
||||
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 inline int |
||||
rgb_to_yuv(uint32_t format, uint32_t p, int *u, int *v) |
||||
{ |
||||
int r, g, b, y; |
||||
|
||||
switch (format) { |
||||
case WCAP_FORMAT_XRGB8888: |
||||
r = (p >> 16) & 0xff; |
||||
g = (p >> 8) & 0xff; |
||||
b = (p >> 0) & 0xff; |
||||
break; |
||||
case WCAP_FORMAT_XBGR8888: |
||||
r = (p >> 0) & 0xff; |
||||
g = (p >> 8) & 0xff; |
||||
b = (p >> 16) & 0xff; |
||||
break; |
||||
} |
||||
|
||||
y = (19595 * r + 38469 * g + 7472 * b) >> 16; |
||||
if (y > 255) |
||||
y = 255; |
||||
|
||||
*u += 46727 * (r - y); |
||||
*v += 36962 * (b - y); |
||||
|
||||
return y; |
||||
} |
||||
|
||||
static inline |
||||
int clamp_uv(int u) |
||||
{ |
||||
int clamp = (u >> 18) + 128; |
||||
|
||||
if (clamp < 0) |
||||
return 0; |
||||
else if (clamp > 255) |
||||
return 255; |
||||
else |
||||
return clamp; |
||||
} |
||||
|
||||
static void |
||||
convert_to_yv12(struct wcap_decoder *decoder, unsigned char *out) |
||||
{ |
||||
unsigned char *y1, *y2, *u, *v; |
||||
uint32_t *p1, *p2, *end; |
||||
int i, u_accum, v_accum, stride0, stride1; |
||||
uint32_t format = decoder->format; |
||||
|
||||
stride0 = decoder->width; |
||||
stride1 = decoder->width / 2; |
||||
for (i = 0; i < decoder->height; i += 2) { |
||||
y1 = out + stride0 * i; |
||||
y2 = y1 + stride0; |
||||
v = out + stride0 * decoder->height + stride1 * i / 2; |
||||
u = v + stride1 * decoder->height / 2; |
||||
p1 = decoder->frame + decoder->width * i; |
||||
p2 = p1 + decoder->width; |
||||
end = p1 + decoder->width; |
||||
|
||||
while (p1 < end) { |
||||
u_accum = 0; |
||||
v_accum = 0; |
||||
y1[0] = rgb_to_yuv(format, p1[0], &u_accum, &v_accum); |
||||
y1[1] = rgb_to_yuv(format, p1[1], &u_accum, &v_accum); |
||||
y2[0] = rgb_to_yuv(format, p2[0], &u_accum, &v_accum); |
||||
y2[1] = rgb_to_yuv(format, p2[1], &u_accum, &v_accum); |
||||
u[0] = clamp_uv(u_accum); |
||||
v[0] = clamp_uv(v_accum); |
||||
|
||||
y1 += 2; |
||||
p1 += 2; |
||||
y2 += 2; |
||||
p2 += 2; |
||||
u++; |
||||
v++; |
||||
} |
||||
} |
||||
} |
||||
|
||||
static void |
||||
output_yuv_frame(struct wcap_decoder *decoder) |
||||
{ |
||||
static char *out; |
||||
int size; |
||||
|
||||
size = decoder->width * decoder->height * 3 / 2; |
||||
if (out == NULL) |
||||
out = malloc(size); |
||||
|
||||
convert_to_yv12(decoder, out); |
||||
printf("FRAME\n"); |
||||
fwrite(out, 1, size, stdout); |
||||
} |
||||
|
||||
static void |
||||
usage(int exit_code) |
||||
{ |
||||
fprintf(stderr, "usage: wcap-snapshot " |
||||
"[--help] [--yuv4mpeg2] [--frame=<frame>] [--all] \n" |
||||
"\t[--rate=<num:denom>] <wcap file>\n\n" |
||||
"\t--help\t\t\tthis help text\n" |
||||
"\t--yuv2mpeg4\t\tdump wcap file in yuv4mpeg format\n" |
||||
"\t--frame=<frame>\t\twrite out the given frame number as png\n" |
||||
"\t--all\t\t\twrite all frames as pngs\n" |
||||
"\t--rate=<num:denom>\treplay frame rate for yuv4mpeg2,\n" |
||||
"\t\t\t\tspecified as an integer fraction\n\n"); |
||||
|
||||
exit(exit_code); |
||||
} |
||||
|
||||
int main(int argc, char *argv[]) |
||||
{ |
||||
struct wcap_decoder *decoder; |
||||
int i, j, output_frame = -1, yuv4mpeg2 = 0, all = 0, has_frame; |
||||
int num = 30, denom = 1; |
||||
char filename[200]; |
||||
uint32_t msecs, frame_time, *frame, frame_size; |
||||
|
||||
for (i = 1, j = 1; i < argc; i++) { |
||||
if (strcmp(argv[i], "--yuv4mpeg2") == 0) { |
||||
yuv4mpeg2 = 1; |
||||
} else if (strcmp(argv[i], "--help") == 0) { |
||||
usage(EXIT_SUCCESS); |
||||
} else if (strcmp(argv[i], "--all") == 0) { |
||||
all = 1; |
||||
} else if (sscanf(argv[i], "--frame=%d", &output_frame) == 1) { |
||||
; |
||||
} else if (sscanf(argv[i], "--rate=%d", &num) == 1) { |
||||
; |
||||
} else if (sscanf(argv[i], "--rate=%d:%d", &num, &denom) == 2) { |
||||
; |
||||
} else if (strcmp(argv[i], "--") == 0) { |
||||
break; |
||||
} else if (argv[i][0] == '-') { |
||||
fprintf(stderr, |
||||
"unknown option or invalid argument: %s\n", argv[i]); |
||||
usage(EXIT_FAILURE); |
||||
} else { |
||||
argv[j++] = argv[i]; |
||||
} |
||||
} |
||||
argc = j; |
||||
|
||||
if (argc != 2) |
||||
usage(EXIT_FAILURE); |
||||
if (denom == 0) { |
||||
fprintf(stderr, "invalid rate, denom can not be 0\n"); |
||||
exit(EXIT_FAILURE); |
||||
} |
||||
|
||||
decoder = wcap_decoder_create(argv[1]); |
||||
|
||||
if (yuv4mpeg2) { |
||||
printf("YUV4MPEG2 C420jpeg W%d H%d F%d:%d Ip A0:0\n", |
||||
decoder->width, decoder->height, num, denom); |
||||
fflush(stdout); |
||||
} |
||||
|
||||
i = 0; |
||||
has_frame = wcap_decoder_get_frame(decoder); |
||||
msecs = decoder->msecs; |
||||
frame_time = 1000 * denom / num; |
||||
frame_size = decoder->width * decoder->height * 4; |
||||
frame = malloc(frame_size); |
||||
while (has_frame) { |
||||
if (decoder->msecs >= msecs) |
||||
memcpy(frame, decoder->frame, frame_size); |
||||
if (all || i == output_frame) { |
||||
snprintf(filename, sizeof filename, |
||||
"wcap-frame-%d.png", i); |
||||
write_png(decoder, filename); |
||||
fprintf(stderr, "wrote %s\n", filename); |
||||
} |
||||
if (yuv4mpeg2) |
||||
output_yuv_frame(decoder); |
||||
i++; |
||||
msecs += frame_time; |
||||
while (decoder->msecs < msecs && has_frame) |
||||
has_frame = wcap_decoder_get_frame(decoder); |
||||
} |
||||
|
||||
fprintf(stderr, "wcap file: size %dx%d, %d frames\n", |
||||
decoder->width, decoder->height, i); |
||||
|
||||
wcap_decoder_destroy(decoder); |
||||
|
||||
return EXIT_SUCCESS; |
||||
} |
@ -1,234 +0,0 @@ |
||||
/*
|
||||
* 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; |
||||
} |
@ -1,157 +0,0 @@ |
||||
/*
|
||||
* 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 |
@ -1,30 +0,0 @@ |
||||
/*
|
||||
* 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; |
||||
} |
@ -1,16 +0,0 @@ |
||||
/*
|
||||
* 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 |
@ -1,2 +0,0 @@ |
||||
|
||||
#define CONFIG_LITTLE_ENDIAN 1 |
@ -1,120 +0,0 @@ |
||||
/*
|
||||
* 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
@ -1,84 +0,0 @@ |
||||
/*
|
||||
* 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> |
||||
|
||||
#include "wcap-decode.h" |
||||
|
||||
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); |
||||
} |
||||
|
||||
int main(int argc, char *argv[]) |
||||
{ |
||||
struct wcap_decoder *decoder; |
||||
int i, output_frame; |
||||
char filename[200]; |
||||
|
||||
if (argc != 2 && argc != 3) { |
||||
fprintf(stderr, "usage: wcap-snapshot 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); |
||||
|
||||
i = 0; |
||||
while (wcap_decoder_get_frame(decoder)) { |
||||
if (i == output_frame) { |
||||
snprintf(filename, sizeof filename, |
||||
"wcap-frame-%d.png", i); |
||||
write_png(decoder, filename); |
||||
printf("wrote %s\n", filename); |
||||
} |
||||
i++; |
||||
} |
||||
|
||||
printf("wcap file: size %dx%d, %d frames\n", |
||||
decoder->width, decoder->height, i); |
||||
|
||||
wcap_decoder_destroy(decoder); |
||||
return EXIT_SUCCESS; |
||||
} |
@ -1,871 +0,0 @@ |
||||
/*
|
||||
* 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; |
||||
} |
@ -1,60 +0,0 @@ |
||||
/*
|
||||
* 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