| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| library fuchsia.mediacodec; |
| |
| // See codec.md for detailed interface documentation. The comments here are a |
| // summary only. Client implementers should see codec.md for more detail on any |
| // message that doesn't seem sufficiently-described here. Codec server |
| // implementers should probably read codec.md before implementing. |
| |
| // Overview of operation: |
| // |
| // 1. Create |
| // * create via CodecFactory - see CodecFactory |
| // 2. Get input constraints |
| // * OnInputConstraints() - sent unsolicited by codec shortly after codec |
| // creation. |
| // 3. Provide input buffers |
| // * SetInputBufferSettings() / AddInputBuffer() |
| // 4. Deliver input data |
| // * QueueInputPacket() + OnFreeInputPacket(), for as long as it takes, |
| // possibly working through all input packets repeatedly before... |
| // 5. Get output constraints and format |
| // * OnOutputConfig() - may be delivered as early as before |
| // OnInputConstraints() by some codecs, but a client must tolerate as late |
| // as after substantial input data has been delivered including lots of |
| // input packet recycling via OnFreeInputPacket(). |
| // * This message can arrive more than once before the first output data. |
| // 6. Provide output buffers |
| // * SetOutputBufferSettings() / AddOutputBuffer() |
| // 7. Data flows, with optional EndOfStream |
| // * OnOutputPacket() / RecycleOutputPacket() / QueueInputPacket() / |
| // OnFreeInputPacket() / QueueInputEndOfStream() / OnOutputEndOfStream() |
| // |
| // It's possible to re-use a Codec instance for another stream, and doing so |
| // can sometimes skip over re-allocation of buffers. This can be a useful thing |
| // to do for cases like seeking to a new location - at the Codec interface that |
| // can look like switching to a new stream. |
| |
| // CodecBufferConstraints |
| // |
| // This struct helps ensure that packet count and buffer space are sufficient |
| // to avoid major problems. For example, a video decoder needs sufficient |
| // video frame buffers to hold all potential reference frames concurrently + |
| // one more video buffer to decode into. Else, the whole video decode pipe can |
| // easily deadlock. |
| // |
| // The secondary purpose of this struct is to help ensure that packet count and |
| // buffer space are sufficient to achieve reasonably performant operation. |
| // |
| // There are separate instances of this struct for codec input and codec output. |
| struct CodecBufferConstraints { |
| // This is a version number the server sets on the constraints to allow the |
| // server to determine when the client has caught up with the latest |
| // constraints sent by the server. The server won't emit output data until |
| // the client has configured output settings and buffers with a |
| // buffer_constraints_version_ordinal >= the latest |
| // buffer_constraints_version_ordinal that had |
| // buffer_constraints_action_required true. See |
| // buffer_constraints_action_required comments for more. |
| // |
| // A buffer_constraints_version_ordinal of 0 is not permitted, to simplify |
| // initial state handling. Other than 0, both odd and even version ordinals |
| // are allowed (in constrast to the stream_lifetime_ordinal, neither the |
| // client nor server ever has a reason to consider the latest version to be |
| // stale, so there would be no benefit to disallowing even values). |
| uint64 buffer_constraints_version_ordinal; |
| |
| // default_settings |
| // |
| // These settings are "default" settings, not "recommended" settings. |
| // |
| // These "default" settings can be passed to SetInputBufferSettings() / |
| // SetOutputBufferSettings() as-is without modification, but a client doing |
| // that must still obey the semantics of packet_count_for_client, despite the |
| // codec server not having any way to really know the proper setting for |
| // that field. |
| // |
| // For CodecBufferConstraints fields whose names end in "recommended", the |
| // default_settings will have the corresponding setting field set to that |
| // recommended value. |
| // |
| // The codec promises that these default settings as-is (except for |
| // buffer_lifetime_ordinal) are guaranteed to |
| // satisfy the constraints indicated by the other fields of |
| // CodecBufferConstraints. While client-side checking that these |
| // settings are within the constraints is likely unnecessary in the client, |
| // the client should still check that these values are within client-side |
| // reasonable-ness bounds before using these values, to avoid letting a codec |
| // server cause problems for the client. |
| // |
| // This structure will always have single_buffer_mode false. See |
| // single_buffer_mode_allowed for whether single_buffer_mode true is allowed. |
| // |
| // The client must set the buffer_lifetime_ordinal field to a proper value |
| // before sending back to the server. The 0 initially in this field will be |
| // rejected by the server if sent back as-is. See comments on |
| // CodecPortBufferSettings.buffer_lifetime_ordinal. |
| CodecPortBufferSettings default_settings; |
| |
| // For uncompresesd video, separate and complete frames, each in its own |
| // separate buffer (buffer-per-packet mode), is always a requirement. |
| |
| // per_packet_buffer_bytes.*: |
| // |
| // These per-packet buffer bytes constraints apply to both buffer-per-packet |
| // mode and single-buffer mode (see single_buffer_mode). If |
| // buffer-per-packet mode, the constraints apply to each buffer separately. |
| // If single-buffer mode, the constraints need to be multiplied by the number |
| // of packets to determine the constraints on the single buffer. |
| |
| // per_packet_buffer_bytes_min: |
| // |
| // If a client is using buffer per packet mode, each buffer must be at least |
| // this large. If a client is using single-buffer mode, the one buffer must |
| // be at least per_packet_buffer_bytes_min * packet_count_for_codec_min in |
| // size. |
| uint32 per_packet_buffer_bytes_min; |
| // Must be >= per_packet_buffer_bytes_min. Delivering more than |
| // this per input packet might not perform any better, and in fact might |
| // perform worse. |
| uint32 per_packet_buffer_bytes_recommended; |
| // Must be >= per_packet_buffer_bytes_recommended. Can be 0xFFFFFFFF if there |
| // is no explicitly-enforced limit. |
| uint32 per_packet_buffer_bytes_max; |
| |
| // Minimum number of packet_count_for_codec. |
| // |
| // Re. input and output: |
| // |
| // This is a strict min for packet_count_for_codec, but a client can use more |
| // packets overall if the client wants to, by using a larger value for |
| // packet_count_for_codec and/or using a non-zero packets_for_client. A good |
| // reason to do the former would be if the client might tend to deliver a few |
| // not-very-full buffers occasionally - or to have a few extra packets within |
| // which to satisfy codec_input_bytes_min. A good reason to do the latter |
| // would be if a client needs to hold onto some packets for any "extra" |
| // duration. |
| // |
| // If a client specifies a larger packet_count_for_codec value than |
| // packet_count_for_codec_min, a server is permitted (but not encouraged) to |
| // not make progress until packet_count_for_codec are with the server, |
| // not merely packet_count_for_codec_min. |
| // |
| // For decoder input and audio encoder input: The packet_count_for_codec_min |
| // may or may not contain enough data to allow the codec to make progress |
| // without copying into an internal side buffer. If there isn't enough data |
| // delivered in packet_count_for_codec_min packets to permit progress, the |
| // codec must copy into its own side buffer internally to make progress. |
| // |
| // If a client intends to use extra packets for client-side purposes, the |
| // client should specify the extra packets in packets_for_client instead of |
| // packet_count_for_codec, but packet_count_for_codec must still be >= |
| // packet_count_for_codec_min. |
| // |
| // See codec.md for more on packet_count_for_codec_min. |
| uint32 packet_count_for_codec_min; |
| |
| // This must be at least packet_count_for_codec_min and at most |
| // packet_count_for_codec_recommended_max. |
| // |
| // This value is likely to be used as-is by most clients, so if having one |
| // additional packet is a big performance win in a large percentage of |
| // scenarios, it can be good for the server to include that additional packet |
| // in this value. |
| uint32 packet_count_for_codec_recommended; |
| |
| // This can be the same as packet_count_for_codec_max or can be lower. |
| // Values above this value and <= packet_count_for_codec_max are not |
| // recommended by the codec, but should still work given sufficient resoures |
| // available to both the client and the codec. |
| uint32 packet_count_for_codec_recommended_max; |
| |
| // This can be 0xFFFFFFFF if there's no codec-enforced max, but codecs are |
| // encouraged to set a large but still plausibly-workable max, and clients |
| // are encouraged to request a number of packets that isn't excessively large |
| // for the client's scenario. |
| uint32 packet_count_for_codec_max; |
| |
| // Normally this would be an implicit 0, but for now we have a min so we can |
| // force the total number of packets to be a specific number that we know |
| // works for the moment. |
| uint32 packet_count_for_client_min; |
| |
| // packet_count_for_client_max |
| // |
| // The client must set packet_count_for_client to be <= |
| // packet_count_for_client_max. |
| // |
| // This value must be at least 1. This can be 0xFFFFFFFF if there's no |
| // codec-enforced max. Clients are encouraged to request a number of |
| // packets that isn't excessively large for the client's scenario. |
| uint32 packet_count_for_client_max; |
| |
| // single_buffer_mode_allowed false allows a codec that's not required to |
| // support single-buffer mode for a given input or output the ability to |
| // decline to support single-buffer mode on that input/output. |
| // |
| // All encoder output, regardless of audio or video: server support for |
| // single-buffer mode is optional. Please see codec.md for all the rules |
| // regarding single-buffer mode on output before using single-buffer mode on |
| // an output. |
| // |
| // Audio decoder output: server support for single-buffer mode is required. |
| // |
| // Video decoder output: There is little reason for a video decoder to |
| // support single-buffer mode on output. Nearly all video decoders will set |
| // this to false for their output. |
| // |
| // All decoder inputs: Servers must support single-buffer mode on input. The |
| // client is responsible for managing the input buffer space such that |
| // filling an input packet doesn't over-write any portion of an input packet |
| // already in flight to the codec. |
| // |
| // Encoder inputs: Server support for single-buffer mode on encoder input is |
| // optional. This is more often useful for audio than for video. |
| // |
| // Support for buffer-per-packet mode is always required on both input and |
| // output, regardless of codec type. |
| bool single_buffer_mode_allowed; |
| |
| // If true, the buffers need to be physically contiguous pages, such as can be |
| // allocated using zx_vmo_create_contiguous(). |
| bool is_physically_contiguous_required; |
| // VERY TEMPORARY HACK / KLUDGE - we want the BufferAllocator (or one of the |
| // participant drivers that needs physically contiguous buffers) to call |
| // zx_vmo_create_contiguous(), definitely not the Codec client, but until the |
| // BufferAllocator can be reached from a driver, this is to grant the client |
| // special powers it really shouldn't have, very temporarily until |
| // BufferAllocator is hooked up properly at which point this can be removed. |
| // Strictly speaking we could reverse which end allocates buffers in the Codec |
| // interface to avoid this hack even before BufferAllocator, but the overall |
| // path seems shorter if we jump directly from this to using BufferAllocator. |
| handle? very_temp_kludge_bti_handle; |
| }; |
| |
| // CodecOutputConfig |
| // |
| // The codec-controlled output configuration, including both |
| // CodecBufferConstraints for the output and CodecFormatDetails for the output. |
| // |
| // TODO(dustingreen): Need a better name for this struct, but still short |
| // hopefully. It's stuff the codec gets to control, not the client. It's |
| // different than output buffer settings, which the client does get to control |
| // to some extent. It's different than any configurable output settings the |
| // client might specifiy for output of an encoder. |
| struct CodecOutputConfig { |
| // A client which always immediately re-configures output buffers on reciept |
| // of OnOutputConfig() with buffer_constraints_action_required true can safely |
| // ignore this field. |
| // |
| // A client is permitted to ignore an OnOutputConfig() message even with |
| // buffer_constraints_action_required true if the client knows the server has |
| // already been told to discard the remainder of the stream with the same |
| // stream_lifetime_ordinal or if this stream_lifetime_ordinal field is set to |
| // 0. The server is required to re-send needed output config via |
| // OnOutputConfig() with new stream_lifetime_ordinal and |
| // buffer_constraints_action_required true, if the the most recent completed |
| // server-side output config isn't what the server wants/needs yet for the |
| // new stream. |
| uint64 stream_lifetime_ordinal; |
| |
| // buffer_constraints_action_required |
| // |
| // When the buffer constraints are delivered, they indicate whether action is |
| // required. A false value here permits delivery of constraints which are |
| // fresher without forcing a buffer reconfiguration. If this is false, a |
| // client cannot assume that it's safe to immediately re-configure output |
| // buffers. If this is true, the client can assume it's safe to immediately |
| // configure output buffers once. |
| // |
| // A client is permitted to ignore buffer constraint versions which have |
| // buffer_constraints_action_required false. The server is not permitted to |
| // change buffer_constraints_action_required from false to true for the same |
| // buffer_constraints_version_ordinal. |
| // |
| // For each configuration, a client must use new buffers, never buffers that |
| // were prevoiusly used for anything else, and never buffers previously used |
| // for any other Codec purposes. This rule exists for multiple good reasons, |
| // relevant to both mid-stream changes, and changes on stream boundaries. |
| // A client should just use new buffers each time. |
| // |
| // When this is true, the server has already de-refed as many low-level |
| // output buffers as the server can while still performing efficient |
| // transition to the new buffers and will de-ref the rest asap. A Sync() is |
| // not necessary to achieve non-overlap of resource usage to the extent |
| // efficiently permitted by the formats involved. |
| // |
| // If buffer_constraints_action_required is true, the server _must_ not |
| // deliver more output data until after output buffers have been configured |
| // (or re-configured) by the client. |
| // |
| // See codec.md for more on buffer_constraints_action_required. |
| bool buffer_constraints_action_required; |
| CodecBufferConstraints buffer_constraints; |
| |
| // format_details |
| // |
| // It's up to the client to determine if a change in |
| // format_details.format_details_version_ordinal implies any client action is |
| // required, based on particular fields in format_details vs. any old value. |
| // The server guarantees that if the format has changed, then |
| // format_details.format_details_version_ordinal will change, but a change to |
| // format_details.format_details_version_ordinal does not guarantee that the |
| // format details actually changed. Servers are strongly encouraged to not |
| // change format_details.format_details_version_ordinal other than before the |
| // first output data of a stream unless there is a real mid-stream format |
| // change in the stream. Unnecessary mid-stream format changes can cause |
| // simpler clients that have no need to handle mid-stream format changes to |
| // just close the channel. Format changes before the first output data of a |
| // stream are not "mid-stream" in this context - those can be useful for |
| // stream format detection / setup reasons. |
| // |
| // Note that in case output buffers don't really need to be re-configured |
| // despite a format change, a server is encouraged, but not required, to |
| // set buffer_constraints_action_required false on the message that conveys |
| // the new format details. Simpler servers may just treat the whole output |
| // situation as one big thing and demand output buffer reconfiguration on any |
| // change in the output situation. |
| // |
| // A client may or may not actually handle a new buffer_constraints with |
| // buffer_constraints_action_required false, but the client should always |
| // track the latest format_details. |
| // |
| // An updated format_details is ordered with respect to emitted output |
| // packets, and applies to all subsequent packets until the next |
| // format_details with larger version_ordinal. A simple client that does not |
| // intend to handle mid-stream format changes should still keep track of the |
| // most recently received format_details until the first output packet |
| // arrives, then lock down the format details, handle those format details, |
| // and verify that any format_details.format_details_version_ordinal received |
| // from the server is the same as the locked-down format_details, until the |
| // client is done with the stream. Even such a simple client must tolerate |
| // format_details.format_details_version_ordinal changing multiple times |
| // before the start of data output from a stream (any stream - the first |
| // stream or a subsequent stream). This allows a codec to request that |
| // output buffers and output format be configured speculatively, and for the |
| // output config to be optionally adjusted by the server before the first |
| // data output from a stream after the server knows everything it needs to |
| // know to fully establish the initial output format details. This |
| // simplifies codec server implementation, and allows a clever codec server |
| // to guess it's output config for lower latency before any input data, while |
| // still being able to fix the output config (including format details) if |
| // the guess turns out to be wrong. |
| // |
| // Whether the format_details.format_details_version_ordinal will actually |
| // change mid-stream is a per-codec and per-stream detail that is not |
| // specified in comments here, and in most cases also depends on whether the |
| // format changes on the input to the codec. Probably it'll be fairly common |
| // for a client to use a format which technically supports mid-stream format |
| // change, but the client happens to know that none of the streams the client |
| // intends to process will ever have a mid-stream format change. |
| CodecFormatDetails format_details; |
| }; |
| |
| // Default values for input and output |
| // CodecBufferConstraints.default_settings.packet_count_for_codec. |
| // |
| // These are defined as "const" in FIDL to avoid all server implementations |
| // needing to separately define their own values, and these should be |
| // reasonable as default values, but strictly speaking this is not intended to |
| // promise that this value won't change from build to build. If a client cares |
| // about a specific number, the client should separately define what that |
| // number is and ensure that CodecPortBufferSettings.packet_count_for_client is |
| // at least large enough. |
| // |
| // In contrast to packet_count_for_client, the packet_count_for_codec is much |
| // more codec-specific, so this file has no numbers for that - each codec will |
| // set those as appropriate for the specific codec. |
| // |
| // These are not "recommended" values, only "default" values, in the sense that |
| // the codec doesn't really know what the correct setting for these values is |
| // for a given client, and if the default is not appropriate for a client, |
| // large problems could result such as deadlock. See the comments on |
| // packet_count_for_client. |
| // |
| // Despite these defaults, every client should ideally care about the |
| // packet_count_for_client setting and should ensure that the setting is at |
| // least large enough to cover the number of packets the client might ever need |
| // to camp on for any non-transient duration concurrently. The defaults are |
| // only intended to be plausible for some clients, not all clients. |
| // |
| // One for the client to be filling and one in transit. |
| const uint32 kDefaultInputPacketCountForClient = 2; |
| // One for the client to be rendering, and one in transit. |
| const uint32 kDefaultOutputPacketCountForClient = 2; |
| |
| // For input, this is the default on a fairly arbitrary basis. |
| // |
| // TODO(dustingreen): Do we want the default for audio encoding to be |
| // single_buffer_mode true instead? If so, we may split this up by audio/video |
| // encoder/decoder. |
| const bool kDefaultInputIsSingleBufferMode = false; |
| const bool kDefaultOutputIsSingleBufferMode = false; |
| |
| // CodecPortBufferSettings |
| // |
| // See relevant corresponding constraints in CodecBufferConstraints. The |
| // settings must satisfy the constraints. |
| // |
| // The client informs the codec of these settings and then separately informs |
| // the codec of each buffer. |
| // |
| // TODO(dustingreen): Rename from CodecPortBufferSettings to CodecBufferSettings |
| // in a separate CL (after some other stuff is out of the way first). |
| struct CodecPortBufferSettings { |
| // buffer_lifetime_ordinal |
| // |
| // The containing message starts a new buffer_lifetime_ordinal. |
| // |
| // There is a separate buffer_lifetime_ordinal for input vs. output. |
| // |
| // Re-use of the same value is not allowed. Values must be odd. Values must |
| // only increase (increasing by more than 2 is permitted). |
| // |
| // A buffer_lifetime_ordinal lifetime starts at SetInputBufferSettings() or |
| // SetOutputBufferSettings(), and ends at the the earlier of |
| // CloseCurrentStream() with release_input_buffers/release_output_buffers set |
| // or SetOutputBufferSettings() with new buffer_lifetime_ordinal in the case |
| // of mid-stream output config change. |
| // |
| // See codec.md for more on buffer_lifetime_ordinal. |
| uint64 buffer_lifetime_ordinal; |
| |
| // buffer_constraints_version_ordinal |
| // |
| // This value indicates which version of constraints the client is/was aware |
| // of so far. |
| // |
| // For input, this must always be 0 because constraints don't change for |
| // input (settings can change, but there's no settings vs current constraints |
| // synchronization issue on input). |
| // |
| // For output, this allows the server to know when the client is sufficiently |
| // caught up before the server will generate any more output. |
| // |
| // When there is no active stream, a client is permitted to re-configure |
| // buffers again using the same buffer_constraints_version_ordinal. |
| // |
| // See codec.md for more on buffer_constraints_version_ordinal. |
| uint64 buffer_constraints_version_ordinal; |
| |
| // The total packet count is split into two pieces to disambiguate how many |
| // packets are allocated for the client to hold onto for whatever reason, vs. |
| // how many packets are allocated for the server to hold onto for whatever |
| // reason. |
| // |
| // Extra packets to provide slack for peformance reasons can be in either |
| // category, but typically packet_count_for_codec_recommended will already |
| // include any performance-relevant slack for the server's benefit. |
| |
| // packet_count_for_codec |
| // |
| // How many packets the client is allocating for the codec server's use. |
| // This must be >= CodecBufferConstraints.packet_count_for_codec_min. If |
| // constraints change such that this would no longer be true, the server will |
| // send an OnOutputConfig() event. |
| // |
| // The codec server is allowed to demand that all of packet_count_for_codec |
| // become free before making further progress, even if |
| // packet_count_for_codec is > packet_count_for_codec_min. |
| // |
| // A reasonable value for this is |
| // CodecBufferConstraints.packet_count_for_codec_recommended. |
| // |
| // See codec.md for more on packet_count_for_codec. |
| uint32 packet_count_for_codec; |
| |
| // packet_count_for_client |
| // |
| // This must be at least 1. The server will close the channel if this is 0. |
| // |
| // How many packets the client is allocating for the client's use. The |
| // client may hold onto this many packets for arbitrarily-long duration |
| // without handing these packets to the codec, and despite doing so, the |
| // codec will continue to make progress and function normally without getting |
| // stuck. The client holding onto additional packets transiently is ok, but |
| // the client needs to hand those additional packets back to the codec |
| // eventually if the client wants the codec to make further progress. |
| // |
| // In addition to this value needing to include at least as many packets as |
| // the client ever intends to concurrently camp on indefinitely, any extra |
| // slack to benefit client-side performance should also be included here. |
| // |
| // A typical value for this could be at least 2, but it depends strongly on |
| // client implementation and overall client buffering goals. It is up to the |
| // client to determine how many packets are needed in this category by any |
| // parts of the overall system that will be holding onto packets for any |
| // reason. Those parts of the system should have a documented and possibly |
| // queryable defined value to help determine this number. Setting this value |
| // lower than it actaully needs to be can result in the codec not making |
| // progress as it sits waiting for packets, with the client unable to recycle |
| // any more packets to the codec. That situation can be difficult to |
| // diagnose, while excessively-large values here are wasteful, so care is |
| // warranted to set this value properly. |
| uint32 packet_count_for_client; |
| |
| // per_packet_buffer_bytes |
| // |
| // In buffer-per-packet mode, we require that each buffer have usable bytes |
| // equal to per_packet_buffer_bytes. Use of differently-sized low-level |
| // buffers is possible, but the size of the portion used via the Codec |
| // interface per CodecBuffer must be the same for all the buffers. |
| // |
| // In single-buffer mode, we require the portion of the low-level buffer used |
| // via the Codec interface to be size (packet_count_for_codec + |
| // packet_count_for_client) * per_packet_buffer_bytes. |
| // |
| // TODO(dustingreen): determine if we need to relax these restrictions a bit |
| // for convenience when using gralloc video buffers. |
| uint32 per_packet_buffer_bytes; |
| |
| // If true, there is only one buffer with index 0 which all packets |
| // implicitly refer to. If false, the packet_index and buffer_index are 1:1, |
| // and each packet refers to its corresponding buffer. |
| // |
| // While it's possible to set up single_buffer_mode false with each buffer |
| // referring to the same underlying VMO, single_buffer_mode true is more |
| // efficient for that case since only one mapping is created. |
| bool single_buffer_mode; |
| }; |
| |
| // CodecBuffer |
| // |
| // The CodecBuffer struct represents a pre-configured buffer. |
| // |
| // Both input and output uses CodecBuffer(s), but the two sets of buffers are |
| // separate. |
| // |
| // The client uses SetInputBufferSettings() + AddInputBuffer() * N to inform |
| // the codec about all the input buffers. |
| // |
| // The client uses SetOutputBufferSettings() + AddOutputBuffer() * N to inform |
| // the codec about all the output buffers. |
| // |
| // When single_buffer_mode is true, there is only buffer_index 0 shared by all |
| // CodecPacket(s) of the relevant input or output. When single_buffer_mode is |
| // false, the buffer_index equals the packet_index. |
| struct CodecBuffer { |
| // When using AddOutputBuffer()/AddInputBuffer(), this must match the |
| // buffer_lifetime_ordinal of the most recent |
| // SetOutputBufferSettings()/SetInputBufferSettings(). |
| uint64 buffer_lifetime_ordinal; |
| |
| // Buffers must be added via AddOutputBuffer() / AddInputBuffer() in order by |
| // buffer_index, and the buffer_index is always equal to 0 or equal to the |
| // packet_index (depending on single_buffer_mode true or false), but it's |
| // still nice to have CodecBuffer include the buffer_index if only for easier |
| // debugging. |
| uint32 buffer_index; |
| |
| // For each new buffer_lifetime_ordinal, a client must use new low-level |
| // buffers. This rule exists for multiple very good reasons, and is relevant |
| // to mid-stream changes, changes on stream boundaries, and both input and |
| // output buffers. A new buffer_lifetime_ordinal needs new low-level |
| // buffers, not just new CodecBuffer(s). If you find yourself copying |
| // compressed input data into new low-level input buffers solely due to this |
| // rule, consider asking the source of the data for the ability to directly |
| // fill new VMOs. The rule exists for good reasons, even for input buffers. |
| // |
| // The previous paragraph does not prohibit carving up VMOs into sub-pieces |
| // and using different sub-pieces as different CodecBuffer(s), with some VMOs |
| // used for more than one CodecBuffer and possibly others used for only one |
| // CodecBuffer. While this is permitted and enables some optimizations, it's |
| // not expected to be particularly common. |
| // |
| // See codec.md for more on CodecBufferData, and more on why we never re-use |
| // the same low-level buffers for different buffer_lifetime_ordinal(s). |
| CodecBufferData data; |
| }; |
| |
| // CodecBufferData |
| // |
| // For the moment, a VMO per buffer is the only type of buffer. |
| // |
| // This is extremely likely to change significantly when adding gralloc stuff, |
| // but the idea with this union is to have a struct per logical way of storing |
| // the data. Any multi-domain storage within a gralloc buffer will likely be |
| // only indirectly represented here. |
| union CodecBufferData { |
| CodecBufferDataVmo vmo; |
| |
| // TODO(dustingreen): add the gralloc way |
| }; |
| |
| // CodecBufferDataVmo |
| // |
| // Details for a buffer backed by a VMO. |
| struct CodecBufferDataVmo { |
| // The same VMO can be used by more than one CodecBuffer (only of the same |
| // buffer_lifetime_ordinal), but each vmo_handle must be a separate handle. |
| handle<vmo> vmo_handle; |
| |
| // Offset within the VMO of the first usable byte. Must be < the VMO's size |
| // in bytes. |
| uint64 vmo_usable_start; |
| |
| // VMO-relative offset that's one past the last usable byte. This can point |
| // one byte beyond the end of the VMO if desired. In other words, this can |
| // be equal to the VMO's size, to indicate that the last byte of the VMO is |
| // usable (and possibly many byte before that, depending on |
| // vmo_usable_start). |
| uint64 vmo_usable_size; |
| }; |
| |
| // CodecPacketHeader |
| // |
| // When referring to a free packet, we use CodecPacketHeader alone instead of |
| // CodecPacket, since while a packet is free it doesn't really have meaningful |
| // offset or length etc. |
| // |
| // A populated CodecPacket also has a CodecPacketHeader. |
| struct CodecPacketHeader { |
| // This is which buffer configuration lifetime this header is referring to. |
| // |
| // A packet_index is only really meaningful with respect to a particular |
| // buffer_lifetime_ordinal. |
| // |
| // See CodecPortBufferSettings.buffer_lifetime_ordinal. |
| // |
| // For QueueInputPacket(), a server receiving a buffer_lifetime_ordinal that |
| // isn't the current input buffer_lifetime_ordinal will close the channel. |
| // |
| // For OnFreeInputPacket() and RecycleOutputPacket(), the reciever (client or |
| // server) must ignore a message with stale buffer_lifetime_ordinal. |
| uint64 buffer_lifetime_ordinal; |
| |
| // The overall set of packet_index values is densely packed from 0..count-1 |
| // for input and output separately. They can be queued in any order. |
| // |
| // Both the client and server should validate the packet_index against the |
| // known bound and disconnect if it's out of bounds. |
| // |
| // When running in buffer-per-packet mode, the packet_index is also the |
| // buffer index. When running in single-buffer mode, the buffer index is |
| // always 0 referring to the single buffer. |
| // |
| // The packet_index values don't imply anything about order of use of |
| // packets. The client should not expect the ordering to remain the same over |
| // time - the codec is free to hold on to an input or output packet for a |
| // while during which other packet_index values may be used multiple times. |
| // |
| // For a given properly-functioning Codec instance, packet_index values will |
| // be unique among concurrently-outstanding packets. Servers should validate |
| // that a client isn't double-using a packet and clients should validate as |
| // necessary to avoid undefined or unexpected client behavior. |
| uint32 packet_index; |
| }; |
| |
| // CodecPacket |
| // |
| // A CodecPacket represents a chunk of input or output data to or from a codec. |
| // |
| // codec output: |
| // While the CodecPacket is outstanding with the client via OnOutputPacket(), |
| // the codec will avoid modifying the referenced output data. After the client |
| // calls RecycleOutputPacket(packet_index), the codec is notified that the |
| // client is again ok with the referenced data changing. |
| // |
| // codec input: |
| // The client initially has all packet_index(es) available to fill, and later |
| // gets packet_index(s) that are again ready to fill via OnFreeInputPacket(). |
| // The client must not modify the referenced data in between QueueInputPacket() |
| // and OnFreeInputPacket(). |
| struct CodecPacket { |
| CodecPacketHeader header; |
| |
| // Which buffer this packet refers to. For single-buffer mode this will |
| // always be 0, but for multi-buffer mode, a given in-flight interval of a |
| // packet can refer to any buffer. The packet has an associated buffer only |
| // while the packet is in-flight, not while the packet is free. |
| // |
| // The default value makes accidental inappropriate use of index 0 less |
| // likely (will tend to complain in an obvious way if not filled out instead |
| // of a non-obvious data corruption when decoding buffer 0 repeatedly instead |
| // of the correct buffers). |
| uint32 buffer_index = 0x80000000; |
| |
| // stream_lifetime_ordinal |
| // |
| // The value 1 is the lowest permitted value after codec creation. Values |
| // sent by the client must be odd. Values must only increase. |
| // |
| // A stream_lifetime_ordinal represents the lifetime of a stream. All |
| // messages that are specific to a stream have the stream_lifetime_ordinal |
| // value and the value is the same for all messages relating to a given |
| // stream. |
| // |
| // See codec.md for more on stream_lifetime_ordinal. |
| uint64 stream_lifetime_ordinal; |
| |
| // start_offset and valid_length_bytes |
| // |
| // Which part of the relevant buffer is this packet using. These are valid |
| // for input data that's in-flight to the codec, and are valid for output data |
| // from the codec. |
| // |
| // For compressed formats and uncompressed audio, the data in |
| // [start_offset, start_offset + valid_length_bytes) is the contiguously valid |
| // data refered to by this packet. |
| // |
| // For uncompressed video frames, CodecFormatDetails is the primary means of |
| // determining which bytes are relevant. The offsets in CodecFormatDetails |
| // are relative to the start_offset here. The valid_length_bytes must be |
| // large enough to include the full last line of pixel data, including the |
| // full line stride of the last line (not just the width in pixels of the |
| // last line). |
| // |
| // Despite these being filled out, some uncompressed video buffers are of |
| // types that are not readable by the CPU. These fields being here don't |
| // imply there's any way for the CPU to read an uncompressed frame. |
| // |
| // TODO(dustingreen): Do we have any reason to require that these be filled |
| // out for opaque uncompressed video frames that the CPU can't read? In that |
| // case do we want to require them just so they can be potentially passed on |
| // to a HW renderer in case the HW renderer has any use for them? Or more |
| // likely, it may just be that these tend to refer to the whole size of an |
| // uncompressed buffer, with format_details taking care of specifying which |
| // bytes are actually relevant. |
| uint32 start_offset; |
| |
| // valid_length_bytes |
| // |
| // This must be > 0. |
| // |
| // The semantics for valid data per packet vary depending on data type as |
| // follows. |
| // |
| // uncompressed video - A video frame can't be split across packets. Each |
| // packet is one video frame. |
| // |
| // uncompressed audio - Regardless of float or int, linear or uLaw, or number |
| // of channels, a packet must contain an non-negative number of complete |
| // audio frames, where a single audio frame consists of data for all the |
| // channels for the same single point in time. Any codec-specific internal |
| // details re. lower rate sampling for LFE channel or the like should be |
| // hidden by the Codec server implementation. |
| // |
| // compressed data input - A packet must contain at least one byte of data. |
| // See also codec_input_bytes_min. Splitting AUs at arbitrary byte |
| // boundaries is permitted, including at boundaries that are in AU headers. |
| // |
| // compressed data output - The codec is not required to fully fill each |
| // output packet's buffer. |
| uint32 valid_length_bytes; |
| |
| // This value is not strictly speaking a timestamp. It is an arbitrary |
| // unsigned 64-bit number that, under some circumstances, will be passed by a |
| // codec unmodified from an input packet to the exactly-corresponding output |
| // packet. |
| // |
| // For timestamp_ish values to be propagated from input to output the |
| // following conditions must be true: |
| // * promise_separate_access_units_on_input must be true |
| // * has_timestamp_ish must be true for a given input packet, to have that |
| // timestamp_ish value (potentially) propagate through to an output |
| // * the Codec instance itself decides (async) that the input packet |
| // generates an output packet - if a given input never generates an output |
| // packet then the timestamp_ish value on the input will never show up on |
| // any output packet - depending on the characteristics of the input and |
| // output formats, and whether a decoder is willing to join mid-stream, etc |
| // this can be more or less likely to occur, but clients should be written |
| // to accomodate timestamp_ish values that are fed on input but never show |
| // up on output, at least to a reasonable degree (not crashing, not |
| // treating as an error). |
| // |
| // See codec.md for more on timestamp_ish. |
| bool has_timestamp_ish; |
| uint64 timestamp_ish; |
| |
| // start_access_unit |
| // |
| // If promise_separate_access_units_on_input (TODO(dustingreen): or any |
| // similar mode for output) is true, this bool must be set appropriately |
| // depending on whether byte 0 _is_ or _is not_ the start of an access unit. |
| // The client is required to know, and required to set this boolean properly. |
| // The server is allowed to infer that when this boolean is false, byte 0 is |
| // the first byte of a continuation of a previously-started AU. (The byte at |
| // start_offset is "byte 0".) |
| // |
| // If promise_separate_access_units_on_input is false, this boolean is |
| // ignored. |
| bool start_access_unit; |
| |
| // known_end_access_unit |
| // |
| // A client is never required to set this boolean to true. |
| // |
| // If promise_separate_access_units_on_input is true, for input data, this |
| // boolean must be false if the last byte of this packet is not the last byte |
| // of an AU, and this boolean _may_ be true if the last byte of this packet |
| // is the last byte of an AU. A client delivering one AU at a time that's |
| // interested in the lowest possible latency via the decoder should set this |
| // boolean to true when it can be set to true. |
| // |
| // If promise_separate_access_units_on_input is false, this boolean is |
| // ignored. |
| bool known_end_access_unit; |
| }; |
| |
| // Codec |
| // |
| // The Codec interface exists to anchor the configuration of input and output |
| // buffers, and depending on Codec server hosting strategy, the Codec inteface |
| // can, in some configurations, be 1:1 with a codec isolate (process), |
| // especially when using SW codecs. The Codec can be used to process up to one |
| // stream at a time. |
| // |
| // Descriptions of actions taken by methods of this interface and the states of |
| // things are given as if the methods are synchronously executed by the codec |
| // server, but in reality, as is typical of FIDL interfaces, the message |
| // processing is async. The states described are to be read as the state from |
| // the client's point of view unless otherwise stated. Events coming back from |
| // the server are of course delivered async, and a client that processes more |
| // than one stream per Codec instance needs to care whether a given event is |
| // from the current stream vs. some older soon-to-be-gone stream. |
| // |
| // The Sync() method's main purpose is to enable the client to robustly prevent |
| // having both old and new buffers allocated in the system at the same time, |
| // since media buffers can be significantly large, depending. The Sync() method |
| // achieves this by only delivering it's response when all previous calls to |
| // the Codec interface have actually taken effect in the StreamControl ordering |
| // domain. Sync() can also be used to wait for the codec server to catch up if |
| // there's a possibility that a client might otherwise get too far ahead of the |
| // Codec server, by for example requesting creation of a large number of |
| // streams in a row. It can also be used during debugging to ensure that a |
| // codec server hasn't gotten stuck. Calling Sync() is entirely optional and |
| // never required for correctness - only potentially required to de-overlap |
| // resource usage. |
| // |
| // Semi-trusted Codec server - SW decoders run in an isolate (with very few |
| // capabilities) just in case the decoding SW has a vulnerability which could |
| // be used to take over the Codec server. Clients of the codec interface using |
| // decoders and processing streams of separate security contexts, to a greater |
| // extent than some other interfaces, need to protect themselves against |
| // invalid server behavior, such as double-free of a packet_index and any other |
| // invalid server behavior. Having fed in compressed data of one security |
| // context, don't place too much trust in a single Codec instance to not mix |
| // data among any buffers that Codec server has ever been told about. Instead, |
| // create separate Codec instances for use by security-separate client-side |
| // contexts. While the picture for HW-based decoders looks somewhat different |
| // and is out of scope of this paragraph, the client should always use separate |
| // Codec instances for security-separate client-side contexts. |
| interface Codec { |
| // EnableOnStreamFailed() |
| // |
| // Permit the server to use OnStreamFailed() instead of the server just |
| // closing the whole Codec channel on stream failure. |
| // |
| // If the server hasn't seen this message by the time a stream fails, the |
| // server will close the Codec channel instead of sending OnStreamFailed(). |
| 1: EnableOnStreamFailed(); |
| |
| // OnStreamFailed() |
| // |
| // The stream has failed, but the Codec instance is still usable for a new |
| // stream. |
| // |
| // This message is only ever sent by the server if the client previously sent |
| // EnableOnStreamFailed(). If the client didn't send EnableOnStreamFailed() |
| // then the server closes the Codec channel instead. |
| // |
| // Codec server implementations are encouraged to handle stream errors (and |
| // ideally to also report them via error_ bools of OnOutputPacket() and |
| // OnOutputEndOfStream()) without failing the whole stream, but if a codec |
| // server is unable to do that, but still can cleanly contain the failure to |
| // the stream, the codec server can (assuming EnableOnStreamFailed() was |
| // called) use OnStreamFailed() to indicate the stream failure to the client |
| // without closing the Codec channel. |
| // |
| // An ideal Codec server handles problems with input data without sending |
| // this message, but sending this message is preferred vs. closing the server |
| // end of the Codec channel if the Codec server can 100% reliably contain the |
| // stream failure to the stream, without any adverse impact to any later |
| // stream. |
| // |
| // No further messages will arrive from the server regarding the failed |
| // stream. This includes any OnOutputEndOfStream() that the client would |
| // have otherwise expected. |
| // |
| // TODO(dustingreen): Add at least an error_message string and _maybe_ a |
| // zx_status_t, though that might tend to encourage mis-use of zx_status_t so |
| // maybe just error_message for quicker debugging on the client side. Also |
| // plumb from CodecAdapterH264 and similar. |
| 2: -> OnStreamFailed(uint64 stream_lifetime_ordinal); |
| |
| // OnInputConstraints() |
| // |
| // The server sends this shortly after Codec creation to indicate input |
| // buffer constraints. The "min" and "max" input constraints don't change |
| // for the life of the Codec. |
| // |
| // The "max" values for buffer size and count are large enough to support the |
| // most demanding format the server supports on input. The "recommended" |
| // values should be workable for use with the input CodecFormatDetails |
| // conveyed during Codec creation. The "recommended" values are not |
| // necessarily suitable if the client uses QueueInputFormatDetails() to |
| // change the input format. In that case it's up to the client to determine |
| // suitable values, either by creating a new Codec instance instead, or |
| // knowing suitable values outside the scope of this protocol. |
| // |
| // See comments on CodecBufferConstraints. |
| // |
| // This message is guaranteed to be sent unsolicited to the Codec client |
| // during or shortly after Codec creation. Clients should not depend on this |
| // being the very first message to arrive at the client. OnOutputConfig() |
| // may be sent first by some codecs that already know their initial output |
| // config without any input data, to encourage (but not stictly require) the |
| // client to configure output buffers before feeding the first input, to |
| // avoid a wasteful OnOutputConfig() being generated for that first stream if |
| // the client has started configuring output but isn't done configuring |
| // output before the client sends the first input data for the first stream. |
| // A client is free to ignore OnOutputConfig() with a stale |
| // stream_lifetime_ordinal, but handling OnOutputConfig() with |
| // stream_lifetime_ordinal 0 (if any are sent) can help reduce latency to |
| // first output. See OnOutputConfig() for more details. |
| // |
| // The "min" and "max" input constraints are guaranteed not to change for a |
| // given Codec instance. The "recommended" values may effectively change |
| // when the server processes QueueInputFormatDetails(). There is not any way |
| // in the protocol short of creating a new Codec instance for the client to |
| // get those new "recommended" values. |
| // |
| // TODO(dustingreen): Maybe provide a way for the client to get updated |
| // "recommended" values for input, maybe only on request rather than via this |
| // event, to keep things simpler for simpler clients. Maybe separate the |
| // recommendations from the constraints. |
| 3: -> OnInputConstraints(CodecBufferConstraints input_constraints); |
| |
| // SetInputBufferSettings() and AddInputBuffer() |
| // |
| // Configuring input buffers consists of calling SetInputBufferSettings() |
| // followed by a number of calls to AddInputBuffer() equal to the number of |
| // buffers set via SetInputBufferSettings(). In buffer-per-packet mode, this |
| // is the same as the number of packets. In single-buffer mode, this is 1. |
| // |
| // After OnInputConstraints(), the client uses these two methods to set up |
| // input buffers and packets. |
| // |
| // Configuring input buffers is required before QueueInputPacket(). |
| // |
| // The client can also re-set-up input buffers any time there is no current |
| // stream. The client need not wait until all previously-set-up input |
| // buffers are with the client via OnFreeInputPacket(). The old |
| // buffer_lifetime_ordinal just ends. See codec.md for more info on "buffer |
| // lifetime". |
| // |
| // The recommended way to de-overlap resource usage (when/if the client wants |
| // to) is to send CloseCurrentStream() with release_input_buffers true then |
| // send Sync() and wait for its response before allocating any new buffers. |
| // How to cause other parts of the system to release their references on |
| // low-level buffers is outside the scope of this interface. |
| // |
| // This call ends any previous buffer_lifetime_ordinal, and starts a new one. |
| 4: SetInputBufferSettings(CodecPortBufferSettings input_settings); |
| |
| // The client is required to add all the input buffers before sending any |
| // message that starts a new stream else the codec will close the Codec |
| // channel. |
| // |
| // When the last buffer is added with this message, all the input packets |
| // effectively jump from non-existent to free with the client. The Codec |
| // will not generate an OnFreeInputPacket() for each new input packet. The |
| // client can immediately start sending QueueInputPacket() after sending the |
| // last AddInputBuffer(). |
| 5: AddInputBuffer(CodecBuffer buffer); |
| |
| // OnOutputConfig() |
| // |
| // This event informs the client of new output config. The server will send |
| // at least one of these messages before the first output packet of a stream, |
| // but that message might not have buffer_constraints_action_required true. |
| // |
| // If buffer_constraints_action_required is true and the |
| // stream_lifetime_ordinal matches the current stream, the client must react |
| // by configuring or re-configuring output buffers. |
| // |
| // Some clients may prefer not to support mid-stream output config changes, |
| // but even those clients are required to process OnOutputConfig() messages |
| // up to the first output packet of each stream, as OnOutputConfig() is used |
| // for stream format detection as well as for potential mid-stream output |
| // config changes. |
| // |
| // For more on OnOutputConfig(), see cocec.md. |
| 6: -> OnOutputConfig(CodecOutputConfig output_config); |
| |
| // SetOutputBufferSettings() and AddOutputBuffer() |
| // |
| // These are not permitted until after the first OnOutputConfig(). |
| // |
| // Roughly speaking, these messages are sent in response to OnOutputConfig() |
| // with buffer_constraints_action_required true. |
| // |
| // Configuring output buffers consists of calling SetOutputBufferSettings() |
| // followed by a number of calls to AddOutputBuffer() equal to the number of |
| // buffers set via SetOutputBufferSettings(). In buffer-per-packet mode, this |
| // is the same as the number of packets. In single-buffer mode, this is 1. |
| // |
| // Configuring output buffers is _required_ after OnOutputConfig() is |
| // received by the client with buffer_constraints_action_required true and |
| // stream_lifetime_ordinal equal to the client's current |
| // stream_lifetime_ordinal (even if there is an active stream), and is |
| // _permitted_ any time there is no current stream. |
| // |
| // For more on SetOutputBufferSettings() and AddOutputBuffer(), see codec.md. |
| 7: SetOutputBufferSettings(CodecPortBufferSettings output_settings); |
| 8: AddOutputBuffer(CodecBuffer buffer); |
| |
| // FlushEndOfStreamAndCloseStream() |
| // |
| // This message is optional. |
| // |
| // This message is only valid after QueueInputEndOfStream() for this stream. |
| // The stream_lifetime_ordinal input parameter must match the |
| // stream_lifetime_ordinal of the QueueInputEndOfStream(), else the server |
| // will close the channel. |
| // |
| // A client can use this message to flush through (not discard) the last |
| // input data of a stream so that the codec server generates corresponding |
| // output data for all the input data before the server moves on to the next |
| // stream, without forcing the client to wait for OnOutputEndOfStream() |
| // before queueing data of another stream. |
| // |
| // The difference between QueueInputEndOfStream() and |
| // FlushEndOfStreamAndCloseStream(): QueueInputEndOfStream() is a promise |
| // from the client that there will not be any more input data for the stream |
| // (and this info is needed by some codecs for the codec to ever emit the very |
| // last output data). The QueueInputEndOfStream() having been sent doesn't |
| // prevent the client from later completely discarding the rest of the |
| // current stream by closing the current stream (with or without a stream |
| // switch). In contrast, FlushEndOfStreamAndCloseStream() is a request from |
| // the client that all the previously-queued input data be processed |
| // including the logical "EndOfStream" showing up as OnOutputEndOfStream() |
| // (in success case) before moving on to any newer stream - this essentially |
| // changes the close-stream handling from discard to flush-through for this |
| // stream only. |
| // |
| // A client using this message can start providing input data for a new |
| // stream without that causing discard of old stream data. That's the purpose |
| // of this message - to allow a client to flush through (not discard) the old |
| // stream's last data (instead of the default when closing or switching |
| // streams which is discard). |
| // |
| // Because the old stream is not done processing yet and the old stream's |
| // data is not being discarded, the client must be prepared to continue to |
| // process OnOutputConfig() messages until the stream_lifetime_ordinal is |
| // done. The client will know the stream_lifetime_ordinal is done when |
| // OnOutputEndOfStream(), OnStreamFailed(), or the Codec channel closes. |
| // |
| // For more on FlushEndOfStreamAndCloseStream(), see codec.md. |
| 9: FlushEndOfStreamAndCloseStream(uint64 stream_lifetime_ordinal); |
| |
| // CloseCurrentStream() |
| // |
| // This "closes" the current stream, leaving no current stream. In addition, |
| // this message can optionally release input buffers or output buffers. |
| // |
| // If there has never been any active stream, the stream_lifetime_ordinal must |
| // be zero or the server will close the channel. If there has been an active |
| // stream, the stream_lifetime_ordinal must be the most recent active stream |
| // whether that stream is still active or not. Else the server will close the |
| // channel. |
| // |
| // Multiple of this message without any new active stream in between is not |
| // to be considered an error, which allows a client to use this message to |
| // close the current stream to stop wasting processing power on a stream the |
| // user no longer cares about, then later decide that buffers should be |
| // released and send this message again with release_input_buffers and/or |
| // release_output_buffers true to get the buffers released, if the client is |
| // interested in trying to avoid overlap in resource usage between old |
| // buffers and new buffers (not all clients are). |
| // |
| // See also Sync(). |
| // |
| // For more on CloseCurrentStream(), see codec.md. |
| 10: CloseCurrentStream( |
| uint64 stream_lifetime_ordinal, |
| bool release_input_buffers, |
| bool release_output_buffers); |
| |
| // Sync() -> () |
| // |
| // On completion, all previous Codec calls have done what they're going to do |
| // server-side, _except_ for processing of data queued using |
| // QueueInputPacket(). |
| // |
| // The main purpose of this call is to enable the client to wait until |
| // CloseCurrentStream() with release_input_buffers and/or |
| // release_output_buffers set to true to take effect, before the client |
| // allocates new buffers and re-sets-up input and/or output buffers. This |
| // de-overlapping of resource usage can be worthwhile for media buffers which |
| // can consume resource types whose overall pools aren't necessarily vast in |
| // comparsion to resources consumed. Especially if a client is reconfiguring |
| // buffers multiple times. |
| // |
| // Note that Sync() prior to allocating new media buffers is not alone |
| // sufficient to achieve non-overlap of media buffer resource usage system |
| // wide, but it can be a useful part of achieving that. |
| // |
| // The Sync() transits the Output ordering domain and the StreamControl |
| // ordering domain, but not the InputData ordering domain. For more on |
| // ordering domains see codec.md. |
| // |
| // This request can be used to avoid hitting kMaxInFlightStreams which is |
| // presently 10. A client that stays <= 8 in-flight streams will comfortably |
| // stay under the limit of 10. While the protocol permits repeated |
| // SetInputBufferSettings() and the like, a client that spams the channel |
| // can expect that the channel will just close if the server or the channel |
| // itself gets too far behind. |
| 11: Sync() -> (); |
| |
| // OnOutputPacket() |
| // |
| // This is how the codec emits an output packet to the codec client. |
| // |
| // Order is significant. |
| // |
| // The client should eventually call RecycleOutputPacket() (possibly after |
| // switching streams multiple times), unless the buffer_lifetime_ordinal has |
| // moved on. A stream change doesn't change which packets are busy with |
| // the client vs. free with the server. See "packet lifetime" in codec.md for |
| // more. |
| // |
| // The relevant buffer is buffer 0 if running in single-buffer mode, or the |
| // buffer index is the same as packet_index if running in buffer-per-packet |
| // mode. |
| // |
| // For low-level buffer types that support it, a Codec is free to emit an |
| // output packet before the low-level buffer actually has any usable data in |
| // the buffer, with the mechanism for signalling the presence of data |
| // separate from the OnOutputPacket() message. For such low-level buffer |
| // types, downstream consumers of data from the emitted packet must |
| // participate in the low-level buffer signalling mechanism to know when it's |
| // safe to consume the data. This is most likely to be relevant when using a |
| // video decoder and gralloc-style buffers. |
| // |
| // The error_ bool(s) allow (but do not require) a Codec server to report |
| // errors that happen during an AU or between AUs. |
| // |
| // The scope of error_detected_before starts at the end of the last delivered |
| // output packet on this stream, or the start of stream if there were no |
| // previous output packets on this stream. The scope ends at the start of |
| // the output_packet. |
| // |
| // The error_detected_before bool is separate so that discontinuities can be |
| // indicated separately from whether the current packet is damaged. |
| // |
| // The scope of error_detected_during is from the start to the end of this |
| // output_packet. |
| 12: -> OnOutputPacket( |
| CodecPacket output_packet, |
| bool error_detected_before, |
| bool error_detected_during); |
| |
| // RecycleOutputPacket() |
| // |
| // After the client is done with an output packet, the client needs to tell |
| // the codec that the output packet can be re-used for more output, via this |
| // method. |
| // |
| // It's not permitted to recycle an output packet that's already free with the |
| // codec server. It's permitted but discouraged for a client to recycle an |
| // output packet that has been deallocated by an explicit or implicit output |
| // buffer de-configuration(). See buffer_lifetime_ordinal for more on that. |
| // A server must ignore any such stale RecycleOutputPacket() calls. |
| // |
| // For more on RecycleOutputPacket(), see codec.md. |
| 13: RecycleOutputPacket(CodecPacketHeader available_output_packet); |
| |
| // OnOutputEndOfStream() |
| // |
| // After QueueInputEndOfStream() is sent by the Codec client, within a |
| // reasonable duration the corresponding OnOutputEndOfStream() will be sent by |
| // the Codec server. Similar to QueueInputEndOfStream(), |
| // OnOutputEndOfStream() is sent a maximum of once per stream. |
| // |
| // No more stream data for this stream will be sent after this message. All |
| // input data for this stream was processed. |
| // |
| // While a Codec client is not required to QueueInputEndOfStream() (unless |
| // the client wants to use FlushEndOfStreamAndCloseStream()), if a Codec |
| // server receives QueueInputEndOfStream(), and the client hasn't closed the |
| // stream, the Codec server must generate a corresponding |
| // OnOutputEndOfStream() if nothing went wrong, or must send |
| // OnStreamFailed(), or must close the server end of the Codec channel. An |
| // ideal Codec server would handle and report stream errors via the error_ |
| // flags and complete stream processing without sending OnStreamFailed(), but |
| // in any case, the above-listed options are the only ways that an |
| // OnOutputEndOfStream() won't happen after QueueInputEndOfStream(). |
| // |
| // There will be no more OnOutputPacket() or OnOutputConfig() messages for |
| // this stream_lifetime_ordinal after this message - if a server doesn't |
| // follow this rule, a client should close the Codec channel. |
| // |
| // The error_detected_before bool has the same semantics as the |
| // error_detected_before bool in OnOutputPacket(). |
| 14: -> OnOutputEndOfStream( |
| uint64 stream_lifetime_ordinal, |
| bool error_detected_before); |
| |
| // |
| // Stream specific messages: |
| // |
| |
| // QueueInputFormatDetails() |
| // |
| // If the input format details are still the same as specified during Codec |
| // creation, this message is unnecessary and does not need to be sent. |
| // |
| // If the stream doesn't exist yet, this message creates the stream. |
| // |
| // All servers must permit QueueInputFormatDetails() at the start of a stream |
| // without failing, as long as the new format is supported by the Codec |
| // instance. Technically this allows for a server to only support the exact |
| // input format set during Codec creation, and that is by design. A client |
| // that tries to switch formats and gets a Codec channel failure should try |
| // again one more time with a fresh Codec instance created with CodecFactory |
| // using the new input format during creation, before giving up. |
| // |
| // These format details override the format details |
| // specified during codec creation for this stream only. The next stream will |
| // default back to the format details set during codec creation. |
| // |
| // For now, QueueInputFormatDetails() sent mid-stream will fail the Codec |
| // channel. Clients shouldn't do this for now. |
| // |
| // This message is permitted at the start of the first stream (just like at |
| // the start of any stream). The format specified need not match what was |
| // specified during codec creation, but if it doesn't match, the Codec channel |
| // might close as described above. |
| 15: QueueInputFormatDetails( |
| uint64 stream_lifetime_ordinal, CodecFormatDetails format_details); |
| |
| // QueueInputPacket() |
| // |
| // This message queues input data to the codec for processing. |
| // |
| // If the stream doesn't exist yet, this message creates the new stream. |
| // |
| // The client is required to be willing to send QueueInputPacket() prior to |
| // the server's first OnOutputConfig(), and is permitted to start a new stream |
| // without output buffers configured yet. |
| // |
| // The client must continue to deliver input data via this message even if the |
| // codec has not yet generated the first OnOutputConfig(), and even if the |
| // Codec is generating OnFreeInputPacket() for previously-queued input |
| // packets. The input data must continue as long as there are free packets |
| // to be assured that the server will ever generate the first |
| // OnOutputConfig(). |
| // |
| // For more on QueueInputPacket(), see codec.md. |
| 16: QueueInputPacket(CodecPacket packet); |
| |
| // OnFreeInputPacket() |
| // |
| // The server sends this message when the codec is done consuming this packet |
| // and the packet can be re-filled by the client. |
| // |
| // This is not sent for all packets when a new buffer_lifetime_ordinal starts |
| // as in that case all the packets are initially free with the client. |
| // |
| // See comments on QueueInputBuffer() and "packet lifetime" in codec.md for |
| // for description of buffer lifetime and packet lifetime. |
| // |
| // After receiving the available input buffer via this event, the codec |
| // client can call later call QueueInputBuffer with appropriate offset and |
| // length set. |
| // |
| // TODO(dustingreen): At the moment, there is no guarantee re. the order of |
| // these messages with respect to the order of QueueInputPacket(), but at |
| // least for decoders, it might be worthwhile to require that servers preserve |
| // the order vs. QueueInputPacket(), to make it easier to feed input from a |
| // ring buffer or similar. For audio encoders it might still make sense. For |
| // video encoders probably not. |
| 17: -> OnFreeInputPacket(CodecPacketHeader free_input_packet); |
| |
| // Inform the server that all QueueInputPacket() messages for this stream |
| // have been sent. |
| // |
| // If the stream isn't closed first (by the client, or by OnStreamFailed(), or |
| // Codec channel closing), there will later be a corresponding |
| // OnOutputEndOfStream(). |
| // |
| // The corresponding OnOutputEndOfStream() message will be generated only if |
| // the server finishes processing the stream before the server sees the |
| // client close the stream (such as by starting a new stream). A way to |
| // force the server to finish the stream before closing is to use |
| // FlushEndOfStreamAndCloseStream() after QueueInputEndOfStream() before any |
| // new stream. Another way to force the server to finish the stream before |
| // closing is to wait for the OnOutputEndOfStream() before taking any action |
| // that closes the stream. |
| // |
| // In addition to serving as an "EndOfStream" marker to make it obvious |
| // client-side when all input data has been processed, if a client never |
| // sends QueueInputEndOfStream(), no amount of waiting will necessarily |
| // result in all input data getting processed through to the output. Some |
| // codecs have some internally-delayed data which only gets pushed through by |
| // additional input data _or_ by this EndOfStream marker. In that sense, |
| // this message can be viewed as a flush-through at InputData domain level, |
| // but the flush-through only takes effect if the codec even gets that far |
| // before the stream is just closed at StreamControl domain level. This |
| // message is not alone sufficient to act as an overall flush-through at |
| // StreamControl level. For that, send this message first and then send |
| // FlushEndOfStreamAndCloseStream() (at which point it becomes possible to |
| // queue input data for a new stream without causing discard of this older |
| // stream's data), or wait for the OnOutputEndOfStream() before closing the |
| // current stream. |
| // |
| // If a client sends QueueInputPacket(), QueueInputFormatDetails(), |
| // QueueInputEndOfStream() for this stream after the first |
| // QueueInputEndOfStream() for this stream, a server should close the Codec |
| // channel. |
| 18: QueueInputEndOfStream(uint64 stream_lifetime_ordinal); |
| }; |