From: John Koleszar Date: Wed, 27 Oct 2010 14:05:55 +0000 (-0400) Subject: vpxenc: add unique track id X-Git-Tag: 1.0_branch~825 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c7c0c05608a883830e2e1a77796b2b66656d75d1;p=profile%2Fivi%2Flibvpx.git vpxenc: add unique track id MKV requires a unique(ish) TrackID element in the track info header. Instead of the current hard-coded ID, take a hash of the video track and use that. This value is not written in the deterministic output mode, despite being a deterministic value itself, to give flexibility to change the hash algorithm and not affect bisecting across the change. Change-Id: I807fc3ea6d1427a151c3ef703269b67e80aef860 --- diff --git a/vpxenc.c b/vpxenc.c index bc69f5d..a8632b8 100644 --- a/vpxenc.c +++ b/vpxenc.c @@ -444,6 +444,9 @@ struct EbmlGlobal off_t cue_pos; off_t cluster_pos; + /* This pointer is to a specific element to be serialized */ + off_t track_id_pos; + /* These pointers are to the size field of the element */ EbmlLoc startSegment; EbmlLoc startCluster; @@ -472,6 +475,18 @@ void Ebml_Serialize(EbmlGlobal *glob, const void *buffer_in, unsigned long len) } +/* Need a fixed size serializer for the track ID. libmkv provdes a 64 bit + * one, but not a 32 bit one. + */ +static void Ebml_SerializeUnsigned32(EbmlGlobal *glob, unsigned long class_id, uint64_t ui) +{ + unsigned char sizeSerialized = 4 | 0x80; + Ebml_WriteID(glob, class_id); + Ebml_Serialize(glob, &sizeSerialized, 1); + Ebml_Serialize(glob, &ui, 4); +} + + static void Ebml_StartSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc, unsigned long class_id) @@ -597,7 +612,8 @@ write_webm_file_header(EbmlGlobal *glob, EbmlLoc start; Ebml_StartSubElement(glob, &start, TrackEntry); Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber); - Ebml_SerializeUnsigned(glob, TrackUID, trackID); + glob->track_id_pos = ftello(glob->stream); + Ebml_SerializeUnsigned32(glob, TrackUID, trackID); Ebml_SerializeUnsigned(glob, TrackType, 1); //video is always 1 Ebml_SerializeString(glob, CodecID, "V_VP8"); { @@ -699,7 +715,7 @@ write_webm_block(EbmlGlobal *glob, static void -write_webm_file_footer(EbmlGlobal *glob) +write_webm_file_footer(EbmlGlobal *glob, long hash) { if(glob->cluster_open) @@ -738,10 +754,63 @@ write_webm_file_footer(EbmlGlobal *glob) /* Patch up the seek info block */ write_webm_seek_info(glob); + + /* Patch up the track id */ + fseeko(glob->stream, glob->track_id_pos, SEEK_SET); + Ebml_SerializeUnsigned32(glob, TrackUID, glob->debug ? 0xDEADBEEF : hash); + fseeko(glob->stream, 0, SEEK_END); } +/* Murmur hash derived from public domain reference implementation at + * http://sites.google.com/site/murmurhash/ + */ +static unsigned int murmur ( const void * key, int len, unsigned int seed ) +{ + const unsigned int m = 0x5bd1e995; + const int r = 24; + + unsigned int h = seed ^ len; + + const unsigned char * data = (const unsigned char *)key; + + while(len >= 4) + { + unsigned int k; + + k = data[0]; + k |= data[1] << 8; + k |= data[2] << 16; + k |= data[3] << 24; + + k *= m; + k ^= k >> r; + k *= m; + + h *= m; + h ^= k; + + data += 4; + len -= 4; + } + + switch(len) + { + case 3: h ^= data[2] << 16; + case 2: h ^= data[1] << 8; + case 1: h ^= data[0]; + h *= m; + }; + + h ^= h >> 13; + h *= m; + h ^= h >> 15; + + return h; +} + + #include "args.h" static const arg_def_t debugmode = ARG_DEF("D", "debug", 0, @@ -979,6 +1048,7 @@ int main(int argc, const char **argv_) int arg_have_framerate = 0; int write_webm = 1; EbmlGlobal ebml = {0}; + uint32_t hash = 0; exec_name = argv_[0]; @@ -1468,8 +1538,14 @@ int main(int argc, const char **argv_) frames_out++; fprintf(stderr, " %6luF", (unsigned long)pkt->data.frame.sz); + if(write_webm) { + /* Update the hash */ + if(!ebml.debug) + hash = murmur(pkt->data.frame.buf, + pkt->data.frame.sz, hash); + write_webm_block(&ebml, &cfg, pkt); } else @@ -1522,7 +1598,7 @@ int main(int argc, const char **argv_) if(write_webm) { - write_webm_file_footer(&ebml); + write_webm_file_footer(&ebml, hash); } else {