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
//! Split `VideoDecoderConfig::extra_data` into `csd-0`/`csd-1` (SPS/PPS) buffers for
//! `AMediaFormat_setBuffer`, re-prepending the Annex-B start code
//! [`mediaway_sw::h264::split_annex_b`] strips off.
//!
//! Pure byte-framing logic, independent of a real `MediaCodec`/`AMediaFormat` session so it is
//! unit-testable without an Android device or NDK — the caller ([`super::video`]) forwards the
//! result straight to `MediaFormat::set_buffer("csd-0"/"csd-1", …)` at `configure()` time.
//!
//! **Real detail** (ADR android/0001 § Decision): [`split_annex_b`] returns NAL bytes
//! **without** the start code (`content_begin = pair[0] + 3`, i.e. the returned slice begins at
//! the NAL header byte) — so a naive "split and forward" would hand `AMediaCodec` bare NAL
//! bytes, not the start-code-prefixed buffers the documented convention calls for. This module
//! re-prepends a canonical 4-byte `00 00 00 01` start code to each split SPS/PPS slice before
//! it is handed to `AMediaFormat::set_buffer`. This crate does not parse the SPS/PPS RBSP for
//! decode purposes — the NAL split is a byte-level framing operation only; `AMediaCodec`
//! remains a black box past this framing step.
use ;
/// Prepend a canonical 4-byte Annex-B start code (`00 00 00 01`) to `nal` (a NAL-header-through-
/// payload slice as returned by [`split_annex_b`], with `emulation_prevention_three_byte`
/// bytes still intact — this is a byte-framing operation, not a bitstream rewrite).
pub
/// Split `extra_data` (Annex-B framed) and return the first SPS (`csd-0`) / PPS (`csd-1`) NAL
/// found, each with a start code re-prepended and ready for `AMediaFormat::set_buffer`.
///
/// Best-effort, not required: [`VideoDecoderConfig::extra_data`](crate::VideoDecoderConfig)
/// "may be empty until first keyframe", and `AMediaCodec` decoders documented-ly accept
/// in-band SPS/PPS from the first pushed packet's own NAL units too — see ADR android/0001 §
/// Decision. Returns `(None, None)` if `extra_data` has no start code, or `None` per slot when
/// no SPS/PPS NAL is found. If `extra_data` contains more than one SPS or PPS (rare but legal),
/// only the first of each is returned — an unhandled edge case this stage (ADR android/0001 §
/// Consequences).
pub