pssh_box/
widevine.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
//! Definitions for PSSH data in the Widevine DRM system.
//
//
// Widevine PSSH data and licence messages use a protobuf encoding, which we decode using the Prost
// crate.

use std::fmt;
use prost::Message;
use serde_json::{json, Value};
use crate::ToBytes;

// This file is generated by Prost in our build script
include!(concat!(env!("OUT_DIR"), "/widevine.rs"));

// include!("widevine-generated.rs");

impl ToBytes for WidevinePsshData {
    fn to_bytes(&self) -> Vec<u8> {
        self.encode_to_vec()
    }
}

impl WidevinePsshData {
    pub fn to_json(&self) -> Value {
        let mut out = json!({});
        if let Some(a) = self.algorithm {
            out["algorithm"] = if a == 0 {
                Value::String(String::from("unencrypted"))
            } else {
                Value::String(String::from("Aesctr"))
            };
        }
        if let Some(p) = &self.provider {
            out["provider"] = Value::String(p.to_string());
        }
        if let Some(p) = &self.policy {
            if !p.is_empty() {
                out["policy"] = Value::String(p.to_string());
            }
        }
        if let Some(cpi) = &self.crypto_period_index {
            out["crypto_period_index"] = Value::String(cpi.to_string());
        }
        if let Some(gl) = &self.grouped_license {
            out["grouped_licence"] = Value::String(hex::encode(gl));
        }
        if let Some(ps) = &self.protection_scheme {
            let scheme = match widevine_pssh_data::ProtectionScheme::try_from(*ps) {
                Ok(s) => String::from(s.as_str_name()),
                Err(_) => format!("unknown ({ps})"),
            };
            out["protection_scheme"] = Value::String(scheme);
        }
        let mut keys = Vec::new();
        for kid in &self.key_id {
            keys.push(Value::String(hex::encode(kid)));
        }
        if !keys.is_empty() {
            out["key_id"] = Value::Array(keys);
        }
        if let Some(cid) = &self.content_id {
            out["content_id"] = Value::String(hex::encode(cid));
        }
        out
    }
}

impl fmt::Debug for WidevinePsshData {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut items = Vec::new();
        if let Some(a) = &self.algorithm {
            items.push(if *a == 0 { String::from("unencrypted") } else { String::from("Aesctr") });
        }
        if let Some(p) = &self.provider {
            items.push(format!("provider: {p}"));
        }
        if let Some(p) = &self.policy {
            if !p.is_empty() {
                items.push(format!("policy: {p}"));
            }
        }
        if let Some(cpi) = &self.crypto_period_index {
            items.push(format!("crypto_period_index: {cpi}"));
        }
        if let Some(gl) = &self.grouped_license {
            items.push(format!("grouped_licence: {}", hex::encode(gl)));
        }
        // In the 2016 version of the protobuf for WidevinePsshData, the protection_scheme field is
        // specified as a uint32. In 2018 versions there is a ProtectionScheme enum which specifies
        // values for the uint32.
        if let Some(ps) = &self.protection_scheme {
            let scheme = match widevine_pssh_data::ProtectionScheme::try_from(*ps) {
                Ok(s) => String::from(s.as_str_name()),
                Err(_) => format!("unknown ({ps})"),
            };
            items.push(format!("protection_scheme: {scheme}"));
        }
        for kid in &self.key_id {
            items.push(format!("keyid: {}", hex::encode(kid)));
        }
        if let Some(cid) = &self.content_id {
            items.push(format!("content_id: {}", hex::encode(cid)));
        }
        write!(f, "WidevinePsshData<{}>", items.join(", "))
    }
}