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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Copyright 2020 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Events reported by VDA over pipe FD.

use std::fmt;
use std::fmt::Display;

use enumn::N;

use super::bindings;
use crate::error::*;

/// Represents a response from libvda.
///
/// Each value corresponds to a value of [`VideoDecodeAccelerator::Result`](https://cs.chromium.org/chromium/src/components/arc/common/video_decode_accelerator.mojom?rcl=128dc1f18791dc4593b9fd671aab84cb72bf6830&l=84).
#[derive(Debug, Clone, Copy, N)]
#[repr(u32)]
pub enum Response {
    Success = bindings::vda_result_SUCCESS,
    IllegalState = bindings::vda_result_ILLEGAL_STATE,
    InvalidArgument = bindings::vda_result_INVALID_ARGUMENT,
    UnreadableInput = bindings::vda_result_UNREADABLE_INPUT,
    PlatformFailure = bindings::vda_result_PLATFORM_FAILURE,
    InsufficientResources = bindings::vda_result_INSUFFICIENT_RESOURCES,
    Cancelled = bindings::vda_result_CANCELLED,
}

impl Response {
    pub(crate) fn new(res: bindings::vda_result_t) -> Response {
        Response::n(res).unwrap_or_else(|| panic!("Unknown response is reported from VDA: {}", res))
    }
}

impl Display for Response {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        use self::Response::*;
        match self {
            Success => write!(f, "success"),
            IllegalState => write!(f, "illegal state"),
            InvalidArgument => write!(f, "invalid argument"),
            UnreadableInput => write!(f, "unreadable input"),
            PlatformFailure => write!(f, "platform failure"),
            InsufficientResources => write!(f, "insufficient resources"),
            Cancelled => write!(f, "cancelled"),
        }
    }
}

impl From<Response> for Result<()> {
    fn from(r: Response) -> Self {
        match r {
            Response::Success => Ok(()),
            _ => Err(Error::LibVdaFailure(r)),
        }
    }
}

/// Represents a notified event from libvda.
#[derive(Debug)]
pub enum Event {
    /// Requests the users to provide output buffers.
    ProvidePictureBuffers {
        min_num_buffers: u32,
        width: i32,
        height: i32,
        visible_rect_left: i32,
        visible_rect_top: i32,
        visible_rect_right: i32,
        visible_rect_bottom: i32,
    },
    /// Notifies the user of a decoded frame ready for display.
    /// These events will arrive in display order.
    PictureReady {
        buffer_id: i32,
        bitstream_id: i32,
        left: i32,
        top: i32,
        right: i32,
        bottom: i32,
    },
    /// Notifies the end of bitstream buffer.
    NotifyEndOfBitstreamBuffer {
        bitstream_id: i32,
    },
    NotifyError(Response),
    /// Notifies the result of operation issued by `Session::reset`.
    ResetResponse(Response),
    /// Notifies the result of operation issued by `Session::flush`.
    FlushResponse(Response),
}

impl Event {
    /// Creates a new `Event` from a `vda_event_t` instance.
    /// This function is safe if `event` was a value read from libvda's pipe.
    pub(crate) unsafe fn new(event: bindings::vda_event_t) -> Result<Event> {
        use self::Event::*;

        let data = event.event_data;
        match event.event_type {
            bindings::vda_event_type_PROVIDE_PICTURE_BUFFERS => {
                let d = data.provide_picture_buffers;
                Ok(ProvidePictureBuffers {
                    min_num_buffers: d.min_num_buffers,
                    width: d.width,
                    height: d.height,
                    visible_rect_left: d.visible_rect_left,
                    visible_rect_top: d.visible_rect_top,
                    visible_rect_right: d.visible_rect_right,
                    visible_rect_bottom: d.visible_rect_bottom,
                })
            }
            bindings::vda_event_type_PICTURE_READY => {
                let d = data.picture_ready;
                Ok(PictureReady {
                    buffer_id: d.picture_buffer_id,
                    bitstream_id: d.bitstream_id,
                    left: d.crop_left,
                    top: d.crop_top,
                    right: d.crop_right,
                    bottom: d.crop_bottom,
                })
            }
            bindings::vda_event_type_NOTIFY_END_OF_BITSTREAM_BUFFER => {
                Ok(NotifyEndOfBitstreamBuffer {
                    bitstream_id: data.bitstream_id,
                })
            }
            bindings::vda_event_type_NOTIFY_ERROR => Ok(NotifyError(Response::new(data.result))),
            bindings::vda_event_type_RESET_RESPONSE => {
                Ok(ResetResponse(Response::new(data.result)))
            }
            bindings::vda_event_type_FLUSH_RESPONSE => {
                Ok(FlushResponse(Response::new(data.result)))
            }
            t => panic!("Unknown event is reported from VDA: {}", t),
        }
    }
}