Thu, 15 Jan 2015 15:59:08 +0100
Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | // Copyright (c) 2010 The WebM project authors. All Rights Reserved. |
michael@0 | 2 | // |
michael@0 | 3 | // Use of this source code is governed by a BSD-style license |
michael@0 | 4 | // that can be found in the LICENSE file in the root of the source |
michael@0 | 5 | // tree. An additional intellectual property rights grant can be found |
michael@0 | 6 | // in the file PATENTS. All contributing project authors may |
michael@0 | 7 | // be found in the AUTHORS file in the root of the source tree. |
michael@0 | 8 | |
michael@0 | 9 | #include "EbmlIDs.h" |
michael@0 | 10 | #include "WebMElement.h" |
michael@0 | 11 | #include <stdio.h> |
michael@0 | 12 | #include <stdint.h> |
michael@0 | 13 | #include <stdlib.h> |
michael@0 | 14 | #include <time.h> |
michael@0 | 15 | |
michael@0 | 16 | #define kVorbisPrivateMaxSize 4000 |
michael@0 | 17 | #define UInt64 uint64_t |
michael@0 | 18 | |
michael@0 | 19 | void writeHeader(EbmlGlobal *glob) { |
michael@0 | 20 | EbmlLoc start; |
michael@0 | 21 | Ebml_StartSubElement(glob, &start, EBML); |
michael@0 | 22 | Ebml_SerializeUnsigned(glob, EBMLVersion, 1); |
michael@0 | 23 | Ebml_SerializeUnsigned(glob, EBMLReadVersion, 1); // EBML Read Version |
michael@0 | 24 | Ebml_SerializeUnsigned(glob, EBMLMaxIDLength, 4); // EBML Max ID Length |
michael@0 | 25 | Ebml_SerializeUnsigned(glob, EBMLMaxSizeLength, 8); // EBML Max Size Length |
michael@0 | 26 | Ebml_SerializeString(glob, DocType, "webm"); // Doc Type |
michael@0 | 27 | Ebml_SerializeUnsigned(glob, DocTypeVersion, 2); // Doc Type Version |
michael@0 | 28 | Ebml_SerializeUnsigned(glob, DocTypeReadVersion, 2); // Doc Type Read Version |
michael@0 | 29 | Ebml_EndSubElement(glob, &start); |
michael@0 | 30 | } |
michael@0 | 31 | |
michael@0 | 32 | void writeSimpleBlock(EbmlGlobal *glob, unsigned char trackNumber, short timeCode, |
michael@0 | 33 | int isKeyframe, unsigned char lacingFlag, int discardable, |
michael@0 | 34 | unsigned char *data, unsigned long dataLength) { |
michael@0 | 35 | unsigned long blockLength = 4 + dataLength; |
michael@0 | 36 | unsigned char flags = 0x00 | (isKeyframe ? 0x80 : 0x00) | (lacingFlag << 1) | discardable; |
michael@0 | 37 | Ebml_WriteID(glob, SimpleBlock); |
michael@0 | 38 | blockLength |= 0x10000000; // TODO check length < 0x0FFFFFFFF |
michael@0 | 39 | Ebml_Serialize(glob, &blockLength, sizeof(blockLength), 4); |
michael@0 | 40 | trackNumber |= 0x80; // TODO check track nubmer < 128 |
michael@0 | 41 | Ebml_Write(glob, &trackNumber, 1); |
michael@0 | 42 | // Ebml_WriteSigned16(glob, timeCode,2); //this is 3 bytes |
michael@0 | 43 | Ebml_Serialize(glob, &timeCode, sizeof(timeCode), 2); |
michael@0 | 44 | flags = 0x00 | (isKeyframe ? 0x80 : 0x00) | (lacingFlag << 1) | discardable; |
michael@0 | 45 | Ebml_Write(glob, &flags, 1); |
michael@0 | 46 | Ebml_Write(glob, data, dataLength); |
michael@0 | 47 | } |
michael@0 | 48 | |
michael@0 | 49 | static UInt64 generateTrackID(unsigned int trackNumber) { |
michael@0 | 50 | UInt64 t = time(NULL) * trackNumber; |
michael@0 | 51 | UInt64 r = rand(); |
michael@0 | 52 | r = r << 32; |
michael@0 | 53 | r += rand(); |
michael@0 | 54 | // UInt64 rval = t ^ r; |
michael@0 | 55 | return t ^ r; |
michael@0 | 56 | } |
michael@0 | 57 | |
michael@0 | 58 | void writeVideoTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing, |
michael@0 | 59 | const char *codecId, unsigned int pixelWidth, unsigned int pixelHeight, |
michael@0 | 60 | unsigned int displayWidth, unsigned int displayHeight, |
michael@0 | 61 | double frameRate) { |
michael@0 | 62 | EbmlLoc start; |
michael@0 | 63 | UInt64 trackID; |
michael@0 | 64 | Ebml_StartSubElement(glob, &start, TrackEntry); |
michael@0 | 65 | Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber); |
michael@0 | 66 | trackID = generateTrackID(trackNumber); |
michael@0 | 67 | Ebml_SerializeUnsigned(glob, TrackUID, trackID); |
michael@0 | 68 | Ebml_SerializeString(glob, CodecName, "VP8"); // TODO shouldn't be fixed |
michael@0 | 69 | |
michael@0 | 70 | Ebml_SerializeUnsigned(glob, TrackType, 1); // video is always 1 |
michael@0 | 71 | Ebml_SerializeString(glob, CodecID, codecId); |
michael@0 | 72 | { |
michael@0 | 73 | EbmlLoc videoStart; |
michael@0 | 74 | Ebml_StartSubElement(glob, &videoStart, Video); |
michael@0 | 75 | Ebml_SerializeUnsigned(glob, PixelWidth, pixelWidth); |
michael@0 | 76 | Ebml_SerializeUnsigned(glob, PixelHeight, pixelHeight); |
michael@0 | 77 | if (pixelWidth != displayWidth) { |
michael@0 | 78 | Ebml_SerializeUnsigned(glob, DisplayWidth, displayWidth); |
michael@0 | 79 | } |
michael@0 | 80 | if (pixelHeight != displayHeight) { |
michael@0 | 81 | Ebml_SerializeUnsigned(glob, DisplayHeight, displayHeight); |
michael@0 | 82 | } |
michael@0 | 83 | Ebml_SerializeFloat(glob, FrameRate, frameRate); |
michael@0 | 84 | Ebml_EndSubElement(glob, &videoStart); // Video |
michael@0 | 85 | } |
michael@0 | 86 | Ebml_EndSubElement(glob, &start); // Track Entry |
michael@0 | 87 | } |
michael@0 | 88 | void writeAudioTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing, |
michael@0 | 89 | const char *codecId, double samplingFrequency, unsigned int channels, |
michael@0 | 90 | unsigned char *private, unsigned long privateSize) { |
michael@0 | 91 | EbmlLoc start; |
michael@0 | 92 | UInt64 trackID; |
michael@0 | 93 | Ebml_StartSubElement(glob, &start, TrackEntry); |
michael@0 | 94 | Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber); |
michael@0 | 95 | trackID = generateTrackID(trackNumber); |
michael@0 | 96 | Ebml_SerializeUnsigned(glob, TrackUID, trackID); |
michael@0 | 97 | Ebml_SerializeUnsigned(glob, TrackType, 2); // audio is always 2 |
michael@0 | 98 | // I am using defaults for thesed required fields |
michael@0 | 99 | /* Ebml_SerializeUnsigned(glob, FlagEnabled, 1); |
michael@0 | 100 | Ebml_SerializeUnsigned(glob, FlagDefault, 1); |
michael@0 | 101 | Ebml_SerializeUnsigned(glob, FlagForced, 1); |
michael@0 | 102 | Ebml_SerializeUnsigned(glob, FlagLacing, flagLacing);*/ |
michael@0 | 103 | Ebml_SerializeString(glob, CodecID, codecId); |
michael@0 | 104 | Ebml_SerializeData(glob, CodecPrivate, private, privateSize); |
michael@0 | 105 | |
michael@0 | 106 | Ebml_SerializeString(glob, CodecName, "VORBIS"); // fixed for now |
michael@0 | 107 | { |
michael@0 | 108 | EbmlLoc AudioStart; |
michael@0 | 109 | Ebml_StartSubElement(glob, &AudioStart, Audio); |
michael@0 | 110 | Ebml_SerializeFloat(glob, SamplingFrequency, samplingFrequency); |
michael@0 | 111 | Ebml_SerializeUnsigned(glob, Channels, channels); |
michael@0 | 112 | Ebml_EndSubElement(glob, &AudioStart); |
michael@0 | 113 | } |
michael@0 | 114 | Ebml_EndSubElement(glob, &start); |
michael@0 | 115 | } |
michael@0 | 116 | void writeSegmentInformation(EbmlGlobal *ebml, EbmlLoc *startInfo, unsigned long timeCodeScale, double duration) { |
michael@0 | 117 | Ebml_StartSubElement(ebml, startInfo, Info); |
michael@0 | 118 | Ebml_SerializeUnsigned(ebml, TimecodeScale, timeCodeScale); |
michael@0 | 119 | Ebml_SerializeFloat(ebml, Segment_Duration, duration * 1000.0); // Currently fixed to using milliseconds |
michael@0 | 120 | Ebml_SerializeString(ebml, 0x4D80, "QTmuxingAppLibWebM-0.0.1"); |
michael@0 | 121 | Ebml_SerializeString(ebml, 0x5741, "QTwritingAppLibWebM-0.0.1"); |
michael@0 | 122 | Ebml_EndSubElement(ebml, startInfo); |
michael@0 | 123 | } |
michael@0 | 124 | |
michael@0 | 125 | /* |
michael@0 | 126 | void Mkv_InitializeSegment(Ebml& ebml_out, EbmlLoc& ebmlLoc) |
michael@0 | 127 | { |
michael@0 | 128 | Ebml_StartSubElement(ebml_out, ebmlLoc, 0x18538067); |
michael@0 | 129 | } |
michael@0 | 130 | |
michael@0 | 131 | void Mkv_InitializeSeek(Ebml& ebml_out, EbmlLoc& ebmlLoc) |
michael@0 | 132 | { |
michael@0 | 133 | Ebml_StartSubElement(ebml_out, ebmlLoc, 0x114d9b74); |
michael@0 | 134 | } |
michael@0 | 135 | void Mkv_WriteSeekInformation(Ebml& ebml_out, SeekStruct& seekInformation) |
michael@0 | 136 | { |
michael@0 | 137 | EbmlLoc ebmlLoc; |
michael@0 | 138 | Ebml_StartSubElement(ebml_out, ebmlLoc, 0x4dbb); |
michael@0 | 139 | Ebml_SerializeString(ebml_out, 0x53ab, seekInformation.SeekID); |
michael@0 | 140 | Ebml_SerializeUnsigned(ebml_out, 0x53ac, seekInformation.SeekPosition); |
michael@0 | 141 | Ebml_EndSubElement(ebml_out, ebmlLoc); |
michael@0 | 142 | } |
michael@0 | 143 | |
michael@0 | 144 | void Mkv_WriteSegmentInformation(Ebml& ebml_out, SegmentInformationStruct& segmentInformation) |
michael@0 | 145 | { |
michael@0 | 146 | Ebml_SerializeUnsigned(ebml_out, 0x73a4, segmentInformation.segmentUID); |
michael@0 | 147 | if (segmentInformation.filename != 0) |
michael@0 | 148 | Ebml_SerializeString(ebml_out, 0x7384, segmentInformation.filename); |
michael@0 | 149 | Ebml_SerializeUnsigned(ebml_out, 0x2AD7B1, segmentInformation.TimecodeScale); |
michael@0 | 150 | Ebml_SerializeUnsigned(ebml_out, 0x4489, segmentInformation.Duration); |
michael@0 | 151 | // TODO date |
michael@0 | 152 | Ebml_SerializeWString(ebml_out, 0x4D80, L"MKVMUX"); |
michael@0 | 153 | Ebml_SerializeWString(ebml_out, 0x5741, segmentInformation.WritingApp); |
michael@0 | 154 | } |
michael@0 | 155 | |
michael@0 | 156 | void Mkv_InitializeTrack(Ebml& ebml_out, EbmlLoc& ebmlLoc) |
michael@0 | 157 | { |
michael@0 | 158 | Ebml_StartSubElement(ebml_out, ebmlLoc, 0x1654AE6B); |
michael@0 | 159 | } |
michael@0 | 160 | |
michael@0 | 161 | static void Mkv_WriteGenericTrackData(Ebml& ebml_out, TrackStruct& track) |
michael@0 | 162 | { |
michael@0 | 163 | Ebml_SerializeUnsigned(ebml_out, 0xD7, track.TrackNumber); |
michael@0 | 164 | Ebml_SerializeUnsigned(ebml_out, 0x73C5, track.TrackUID); |
michael@0 | 165 | Ebml_SerializeUnsigned(ebml_out, 0x83, track.TrackType); |
michael@0 | 166 | Ebml_SerializeUnsigned(ebml_out, 0xB9, track.FlagEnabled ? 1 :0); |
michael@0 | 167 | Ebml_SerializeUnsigned(ebml_out, 0x88, track.FlagDefault ? 1 :0); |
michael@0 | 168 | Ebml_SerializeUnsigned(ebml_out, 0x55AA, track.FlagForced ? 1 :0); |
michael@0 | 169 | if (track.Language != 0) |
michael@0 | 170 | Ebml_SerializeString(ebml_out, 0x22B59C, track.Language); |
michael@0 | 171 | if (track.CodecID != 0) |
michael@0 | 172 | Ebml_SerializeString(ebml_out, 0x86, track.CodecID); |
michael@0 | 173 | if (track.CodecPrivate != 0) |
michael@0 | 174 | Ebml_SerializeData(ebml_out, 0x63A2, track.CodecPrivate, track.CodecPrivateLength); |
michael@0 | 175 | if (track.CodecName != 0) |
michael@0 | 176 | Ebml_SerializeWString(ebml_out, 0x258688, track.CodecName); |
michael@0 | 177 | } |
michael@0 | 178 | |
michael@0 | 179 | void Mkv_WriteVideoTrack(Ebml& ebml_out, TrackStruct & track, VideoTrackStruct& video) |
michael@0 | 180 | { |
michael@0 | 181 | EbmlLoc trackHeadLoc, videoHeadLoc; |
michael@0 | 182 | Ebml_StartSubElement(ebml_out, trackHeadLoc, 0xAE); // start Track |
michael@0 | 183 | Mkv_WriteGenericTrackData(ebml_out, track); |
michael@0 | 184 | Ebml_StartSubElement(ebml_out, videoHeadLoc, 0xE0); // start Video |
michael@0 | 185 | Ebml_SerializeUnsigned(ebml_out, 0x9A, video.FlagInterlaced ? 1 :0); |
michael@0 | 186 | Ebml_SerializeUnsigned(ebml_out, 0xB0, video.PixelWidth); |
michael@0 | 187 | Ebml_SerializeUnsigned(ebml_out, 0xBA, video.PixelHeight); |
michael@0 | 188 | Ebml_SerializeUnsigned(ebml_out, 0x54B0, video.PixelDisplayWidth); |
michael@0 | 189 | Ebml_SerializeUnsigned(ebml_out, 0x54BA, video.PixelDisplayHeight); |
michael@0 | 190 | Ebml_SerializeUnsigned(ebml_out, 0x54B2, video.displayUnit); |
michael@0 | 191 | Ebml_SerializeFloat(ebml_out, 0x2383E3, video.FrameRate); |
michael@0 | 192 | Ebml_EndSubElement(ebml_out, videoHeadLoc); |
michael@0 | 193 | Ebml_EndSubElement(ebml_out, trackHeadLoc); |
michael@0 | 194 | |
michael@0 | 195 | } |
michael@0 | 196 | |
michael@0 | 197 | void Mkv_WriteAudioTrack(Ebml& ebml_out, TrackStruct & track, AudioTrackStruct& video) |
michael@0 | 198 | { |
michael@0 | 199 | EbmlLoc trackHeadLoc, audioHeadLoc; |
michael@0 | 200 | Ebml_StartSubElement(ebml_out, trackHeadLoc, 0xAE); |
michael@0 | 201 | Mkv_WriteGenericTrackData(ebml_out, track); |
michael@0 | 202 | Ebml_StartSubElement(ebml_out, audioHeadLoc, 0xE0); // start Audio |
michael@0 | 203 | Ebml_SerializeFloat(ebml_out, 0xB5, video.SamplingFrequency); |
michael@0 | 204 | Ebml_SerializeUnsigned(ebml_out, 0x9F, video.Channels); |
michael@0 | 205 | Ebml_SerializeUnsigned(ebml_out, 0x6264, video.BitDepth); |
michael@0 | 206 | Ebml_EndSubElement(ebml_out, audioHeadLoc); // end audio |
michael@0 | 207 | Ebml_EndSubElement(ebml_out, trackHeadLoc); |
michael@0 | 208 | } |
michael@0 | 209 | |
michael@0 | 210 | void Mkv_WriteEbmlClusterHead(Ebml& ebml_out, EbmlLoc& ebmlLoc, ClusterHeadStruct & clusterHead) |
michael@0 | 211 | { |
michael@0 | 212 | Ebml_StartSubElement(ebml_out, ebmlLoc, 0x1F43B675); |
michael@0 | 213 | Ebml_SerializeUnsigned(ebml_out, 0x6264, clusterHead.TimeCode); |
michael@0 | 214 | } |
michael@0 | 215 | |
michael@0 | 216 | void Mkv_WriteSimpleBlockHead(Ebml& ebml_out, EbmlLoc& ebmlLoc, SimpleBlockStruct& block) |
michael@0 | 217 | { |
michael@0 | 218 | Ebml_StartSubElement(ebml_out, ebmlLoc, 0xA3); |
michael@0 | 219 | Ebml_Write1UInt(ebml_out, block.TrackNumber); |
michael@0 | 220 | Ebml_WriteSigned16(ebml_out,block.TimeCode); |
michael@0 | 221 | unsigned char flags = 0x00 | (block.iskey ? 0x80:0x00) | (block.lacing << 1) | block.discardable; |
michael@0 | 222 | Ebml_Write1UInt(ebml_out, flags); // TODO this may be the wrong function |
michael@0 | 223 | Ebml_Serialize(ebml_out, block.data, block.dataLength); |
michael@0 | 224 | Ebml_EndSubElement(ebml_out,ebmlLoc); |
michael@0 | 225 | } |
michael@0 | 226 | */ |