tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

videoDecoder-codec-specific-setup.js (8353B)


      1 const AV1_DATA = {
      2  src: 'av1.mp4',
      3  config: {
      4    codec: 'av01.0.04M.08',
      5    codedWidth: 320,
      6    codedHeight: 240,
      7    visibleRect: {x: 0, y: 0, width: 320, height: 240},
      8    displayWidth: 320,
      9    displayHeight: 240,
     10  },
     11  chunks: [
     12    {offset: 48, size: 1938}, {offset: 1986, size: 848},
     13    {offset: 2834, size: 3}, {offset: 2837, size: 47}, {offset: 2884, size: 3},
     14    {offset: 2887, size: 116}, {offset: 3003, size: 3},
     15    {offset: 3006, size: 51}, {offset: 3057, size: 25},
     16    {offset: 3082, size: 105}
     17  ]
     18 };
     19 
     20 const VP8_DATA = {
     21  src: 'vp8.webm',
     22  config: {
     23    codec: 'vp8',
     24    codedWidth: 320,
     25    codedHeight: 240,
     26    visibleRect: {x: 0, y: 0, width: 320, height: 240},
     27    displayWidth: 320,
     28    displayHeight: 240,
     29  },
     30  chunks: [
     31    {offset: 522, size: 4826}, {offset: 5355, size: 394},
     32    {offset: 5756, size: 621}, {offset: 6384, size: 424},
     33    {offset: 6815, size: 532}, {offset: 7354, size: 655},
     34    {offset: 8016, size: 670}, {offset: 8693, size: 2413},
     35    {offset: 11113, size: 402}, {offset: 11522, size: 686}
     36  ]
     37 };
     38 
     39 const VP9_DATA = {
     40  src: 'vp9.mp4',
     41  // TODO(sandersd): Verify that the file is actually level 1.
     42  config: {
     43    codec: 'vp09.00.10.08',
     44    codedWidth: 320,
     45    codedHeight: 240,
     46    displayAspectWidth: 320,
     47    displayAspectHeight: 240,
     48  },
     49  chunks: [
     50    {offset: 44, size: 3315}, {offset: 3359, size: 203},
     51    {offset: 3562, size: 245}, {offset: 3807, size: 172},
     52    {offset: 3979, size: 312}, {offset: 4291, size: 170},
     53    {offset: 4461, size: 195}, {offset: 4656, size: 181},
     54    {offset: 4837, size: 356}, {offset: 5193, size: 159}
     55  ]
     56 };
     57 
     58 const H264_AVC_DATA = {
     59  src: 'h264.mp4',
     60  config: {
     61    codec: 'avc1.64000b',
     62    description: {offset: 9490, size: 45},
     63    codedWidth: 320,
     64    codedHeight: 240,
     65    displayAspectWidth: 320,
     66    displayAspectHeight: 240,
     67  },
     68  chunks: [
     69    {offset: 48, size: 4140}, {offset: 4188, size: 604},
     70    {offset: 4792, size: 475}, {offset: 5267, size: 561},
     71    {offset: 5828, size: 587}, {offset: 6415, size: 519},
     72    {offset: 6934, size: 532}, {offset: 7466, size: 523},
     73    {offset: 7989, size: 454}, {offset: 8443, size: 528}
     74  ]
     75 };
     76 
     77 const H264_SEI_AVC_DATA = {
     78  src: 'h264_sei.mp4',
     79  config: {
     80    codec: 'avc1.64000b',
     81    description: {offset: 11989, size: 46},
     82    codedWidth: 320,
     83    codedHeight: 240,
     84    displayAspectWidth: 320,
     85    displayAspectHeight: 240,
     86  },
     87  chunks: [
     88    {offset: 48, size: 4229, key: true}, {offset: 4277, size: 1114},
     89    {offset: 5391, size: 320}, {offset: 5711, size: 188},
     90    {offset: 5899, size: 173}, {offset: 6072, size: 3694, key: true},
     91    {offset: 9766, size: 936}, {offset: 10702, size: 345},
     92    {offset: 11047, size: 213}, {offset: 11260, size: 210}
     93  ]
     94 };
     95 
     96 const H264_ANNEXB_DATA = {
     97  src: 'h264.annexb',
     98  config: {
     99    codec: 'avc1.64000b',
    100    codedWidth: 320,
    101    codedHeight: 240,
    102    displayAspectWidth: 320,
    103    displayAspectHeight: 240,
    104  },
    105  chunks: [
    106    {offset: 0, size: 4175}, {offset: 4175, size: 602},
    107    {offset: 4777, size: 473}, {offset: 5250, size: 559},
    108    {offset: 5809, size: 585}, {offset: 6394, size: 517},
    109    {offset: 6911, size: 530}, {offset: 7441, size: 521},
    110    {offset: 7962, size: 452}, {offset: 8414, size: 526}
    111  ]
    112 };
    113 
    114 const H264_SEI_ANNEXB_DATA = {
    115  src: 'h264_sei.annexb',
    116  config: {
    117    codec: 'avc1.64000b',
    118    codedWidth: 320,
    119    codedHeight: 240,
    120    displayAspectWidth: 320,
    121    displayAspectHeight: 240,
    122  },
    123  chunks: [
    124    {offset: 0, size: 4264, key: true}, {offset: 4264, size: 1112},
    125    {offset: 5376, size: 318}, {offset: 5694, size: 186},
    126    {offset: 5880, size: 171}, {offset: 6051, size: 3729, key: true},
    127    {offset: 9780, size: 934}, {offset: 10714, size: 343},
    128    {offset: 11057, size: 211}, {offset: 11268, size: 208}
    129  ]
    130 };
    131 
    132 const H265_HEVC_DATA = {
    133  src: 'h265.mp4',
    134  config: {
    135    codec: 'hev1.1.6.L60.90',
    136    description: {offset: 5821, size: 2406},
    137    codedWidth: 320,
    138    codedHeight: 240,
    139    displayAspectWidth: 320,
    140    displayAspectHeight: 240,
    141  },
    142  chunks: [
    143    {offset: 44, size: 2515}, {offset: 2559, size: 279},
    144    {offset: 2838, size: 327}, {offset: 3165, size: 329},
    145    {offset: 3494, size: 308}, {offset: 3802, size: 292},
    146    {offset: 4094, size: 352}, {offset: 4446, size: 296},
    147    {offset: 4742, size: 216}, {offset: 4958, size: 344}
    148  ]
    149 };
    150 
    151 const H265_ANNEXB_DATA = {
    152  src: 'h265.annexb',
    153  config: {
    154    codec: 'hev1.1.6.L60.90',
    155    codedWidth: 320,
    156    codedHeight: 240,
    157    displayAspectWidth: 320,
    158    displayAspectHeight: 240,
    159  },
    160  chunks: [
    161    {offset: 0, size: 4894}, {offset: 4894, size: 279},
    162    {offset: 5173, size: 327}, {offset: 5500, size: 329},
    163    {offset: 5829, size: 308}, {offset: 6137, size: 292},
    164    {offset: 6429, size: 352}, {offset: 6781, size: 296},
    165    {offset: 7077, size: 216}, {offset: 7293, size: 344}
    166  ]
    167 };
    168 
    169 // Note: We only test AVC format since with AnnexB there's not enough
    170 // information ahead of the first decode() call to determine if the content is
    171 // interlaced or not.
    172 const H264_INTERLACED_AVC_DATA = {
    173  src: 'h264_interlaced.mp4',
    174  config: {
    175    codec: 'avc1.64000b',
    176    description: {offset: 7501, size: 47},
    177    codedWidth: 320,
    178    codedHeight: 240,
    179    displayAspectWidth: 320,
    180    displayAspectHeight: 240,
    181  },
    182  chunks: [
    183    {offset: 48, size: 4091}, {offset: 4139, size: 949},
    184    {offset: 5088, size: 260}, {offset: 5348, size: 134},
    185    {offset: 5482, size: 111}, {offset: 5593, size: 660},
    186    {offset: 6253, size: 197}, {offset: 6450, size: 96},
    187    {offset: 6546, size: 159}, {offset: 6705, size: 277}
    188  ]
    189 };
    190 
    191 // Allows mutating `callbacks` after constructing the VideoDecoder, wraps calls
    192 // in t.step().
    193 function createVideoDecoder(t, callbacks) {
    194  return new VideoDecoder({
    195    output(frame) {
    196      if (callbacks && callbacks.output) {
    197        t.step(() => callbacks.output(frame));
    198      } else {
    199        t.unreached_func('unexpected output()');
    200      }
    201    },
    202    error(e) {
    203      if (callbacks && callbacks.error) {
    204        t.step(() => callbacks.error(e));
    205      } else {
    206        t.unreached_func('unexpected error()');
    207      }
    208    }
    209  });
    210 }
    211 
    212 function createCorruptChunk(index) {
    213  let bad_data = CHUNK_DATA[index];
    214  // AV1 may require more extensive corruption to trigger decoding errors with
    215  // some software decoders (e.g., dav1d).
    216  let skip = CONFIG.codec.indexOf('av01') >= 0 ? 2 : 4;
    217  for (var i = 0; i < bad_data.byteLength; i += skip) {
    218    bad_data[i] = 0xFF;
    219  }
    220  return new EncodedVideoChunk(
    221      {type: 'delta', timestamp: index, data: bad_data});
    222 }
    223 
    224 // Create a view of an ArrayBuffer.
    225 function view(buffer, {offset, size}) {
    226  return new Uint8Array(buffer, offset, size);
    227 }
    228 
    229 async function checkImplements() {
    230  // Don't run any tests if the codec is not supported.
    231  assert_equals('function', typeof VideoDecoder.isConfigSupported);
    232  let supported = false;
    233  try {
    234    // TODO(sandersd): To properly support H.264 in AVC format, this should
    235    // include the `description`. For now this test assumes that H.264 Annex B
    236    // support is the same as H.264 AVC support.
    237    const support = await VideoDecoder.isConfigSupported({codec: CONFIG.codec});
    238    supported = support.supported;
    239  } catch (e) {
    240  }
    241  assert_implements_optional(supported, CONFIG.codec + ' unsupported');
    242 }
    243 
    244 let CONFIG = null;
    245 let CHUNK_DATA = null;
    246 let CHUNKS = null;
    247 promise_setup(async () => {
    248  const data = {
    249    '?av1': AV1_DATA,
    250    '?vp8': VP8_DATA,
    251    '?vp9': VP9_DATA,
    252    '?h264_avc': H264_AVC_DATA,
    253    '?h264_sei_avc': H264_SEI_AVC_DATA,
    254    '?h264_interlaced_avc': H264_INTERLACED_AVC_DATA,
    255    '?h264_annexb': H264_ANNEXB_DATA,
    256    '?h264_sei_annexb': H264_SEI_ANNEXB_DATA,
    257    '?h265_hevc': H265_HEVC_DATA,
    258    '?h265_annexb': H265_ANNEXB_DATA
    259  }[location.search];
    260 
    261  // Fetch the media data and prepare buffers.
    262  const response = await fetch(data.src);
    263  const buf = await response.arrayBuffer();
    264 
    265  CONFIG = {...data.config};
    266  if (data.config.description) {
    267    CONFIG.description = view(buf, data.config.description);
    268  }
    269 
    270  CHUNK_DATA = data.chunks.map((chunk, i) => view(buf, chunk));
    271 
    272  CHUNKS =
    273      CHUNK_DATA.map((encoded_data, i) => new EncodedVideoChunk({
    274                       type: (i == 0 || data.chunks[i].key) ? 'key' : 'delta',
    275                       timestamp: i,
    276                       duration: 1,
    277                       data: encoded_data
    278                     }));
    279 });