flv_codec/
tag.rs

1use bytecodec::bytes::{BytesEncoder, RemainingBytesDecoder};
2use bytecodec::combinator::{Length, Peekable};
3use bytecodec::fixnum::{U24beDecoder, U24beEncoder, U32beEncoder, U8Decoder, U8Encoder};
4use bytecodec::{ByteCount, Decode, DecodeExt, Encode, Eos, ErrorKind, Result, SizedEncode};
5
6use {
7    AacPacketType, AvcPacketType, CodecId, FrameType, SoundFormat, SoundRate, SoundSize, SoundType,
8    StreamId, TimeOffset, Timestamp,
9};
10
11const TAG_TYPE_AUDIO: u8 = 8;
12const TAG_TYPE_VIDEO: u8 = 9;
13const TAG_TYPE_SCRIPT_DATA: u8 = 18;
14
15/// FLV tag.
16#[derive(Debug, Clone)]
17pub enum Tag<Data = Vec<u8>> {
18    /// Audio tag.
19    Audio(AudioTag<Data>),
20
21    /// Video tag.
22    Video(VideoTag<Data>),
23
24    /// Script data tag.
25    ScriptData(ScriptDataTag<Data>),
26}
27impl<Data> Tag<Data> {
28    /// Returns the kind of the tag.
29    pub fn kind(&self) -> TagKind {
30        match self {
31            Tag::Audio(_) => TagKind::Audio,
32            Tag::Video(_) => TagKind::Video,
33            Tag::ScriptData(_) => TagKind::ScriptData,
34        }
35    }
36
37    /// Returns the timestamp of the tag.
38    pub fn timestamp(&self) -> Timestamp {
39        match self {
40            Tag::Audio(t) => t.timestamp,
41            Tag::Video(t) => t.timestamp,
42            Tag::ScriptData(t) => t.timestamp,
43        }
44    }
45
46    /// Returns the stream identifier of the tag.
47    pub fn stream_id(&self) -> StreamId {
48        match self {
49            Tag::Audio(t) => t.stream_id,
50            Tag::Video(t) => t.stream_id,
51            Tag::ScriptData(t) => t.stream_id,
52        }
53    }
54}
55impl<Data: AsRef<[u8]>> Tag<Data> {
56    /// Returns the number of bytes required to encode this tag.
57    pub fn tag_size(&self) -> u32 {
58        match self {
59            Tag::Audio(t) => t.tag_size(),
60            Tag::Video(t) => t.tag_size(),
61            Tag::ScriptData(t) => t.tag_size(),
62        }
63    }
64}
65impl<Data> From<AudioTag<Data>> for Tag<Data> {
66    fn from(f: AudioTag<Data>) -> Self {
67        Tag::Audio(f)
68    }
69}
70impl<Data> From<VideoTag<Data>> for Tag<Data> {
71    fn from(f: VideoTag<Data>) -> Self {
72        Tag::Video(f)
73    }
74}
75impl<Data> From<ScriptDataTag<Data>> for Tag<Data> {
76    fn from(f: ScriptDataTag<Data>) -> Self {
77        Tag::ScriptData(f)
78    }
79}
80
81/// Tag kind.
82#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
83#[allow(missing_docs)]
84pub enum TagKind {
85    Audio = TAG_TYPE_AUDIO as isize,
86    Video = TAG_TYPE_VIDEO as isize,
87    ScriptData = TAG_TYPE_SCRIPT_DATA as isize,
88}
89
90/// Audio tag.
91#[derive(Debug, Clone)]
92pub struct AudioTag<Data = Vec<u8>> {
93    /// Timestamp.
94    pub timestamp: Timestamp,
95
96    /// Stream identifier.
97    pub stream_id: StreamId,
98
99    /// Sound format.
100    pub sound_format: SoundFormat,
101
102    /// Sound rate.
103    pub sound_rate: SoundRate,
104
105    /// Sound size.
106    pub sound_size: SoundSize,
107
108    /// Sound yype.
109    pub sound_type: SoundType,
110
111    /// AAC packet type.
112    ///
113    /// This is only present if `sound_format == SoundFormat::Aac`.
114    pub aac_packet_type: Option<AacPacketType>,
115
116    /// Audio data.
117    pub data: Data,
118}
119impl<Data: AsRef<[u8]>> AudioTag<Data> {
120    /// Returns the number of bytes required to encode this tag.
121    pub fn tag_size(&self) -> u32 {
122        let mut size = TagHeader::SIZE + 1 + self.data.as_ref().len() as u32;
123        if self.aac_packet_type.is_some() {
124            size += 1;
125        }
126        size
127    }
128}
129
130/// Video tag.
131#[derive(Debug, Clone)]
132pub struct VideoTag<Data = Vec<u8>> {
133    /// Timestamp.
134    pub timestamp: Timestamp,
135
136    /// Stream identifier.
137    pub stream_id: StreamId,
138
139    /// Frame type.
140    pub frame_type: FrameType,
141
142    /// Codec identifier.
143    pub codec_id: CodecId,
144
145    /// AAC packet type.
146    ///
147    /// This is only present if `codec_id == CodecId::Avc` and
148    /// `frame_type != FrameType::VideoInfoOrCommandFrame`.
149    pub avc_packet_type: Option<AvcPacketType>,
150
151    /// Composition time offset.
152    ///
153    /// This is only present if `codec_id == CodecId::Avc` and
154    /// `frame_type != FrameType::VideoInfoOrCommandFrame`.
155    pub composition_time: Option<TimeOffset>,
156
157    /// Video data.
158    pub data: Data,
159}
160impl<Data: AsRef<[u8]>> VideoTag<Data> {
161    /// Returns the number of bytes required to encode this tag.
162    pub fn tag_size(&self) -> u32 {
163        let mut size = TagHeader::SIZE + 1 + self.data.as_ref().len() as u32;
164        if self.avc_packet_type.is_some() {
165            size += 4;
166        }
167        size
168    }
169}
170
171/// Script data tag.
172#[derive(Debug, Clone)]
173pub struct ScriptDataTag<Data = Vec<u8>> {
174    /// Timestamp.
175    pub timestamp: Timestamp,
176
177    /// Stream identifier.
178    pub stream_id: StreamId,
179
180    /// [AMF 0] encoded data.
181    ///
182    /// [AMF 0]: https://wwwimages2.adobe.com/content/dam/acom/en/devnet/pdf/amf0-file-format-specification.pdf
183    pub data: Data,
184}
185impl<Data: AsRef<[u8]>> ScriptDataTag<Data> {
186    /// Returns the number of bytes required to encode this tag.
187    pub fn tag_size(&self) -> u32 {
188        TagHeader::SIZE + self.data.as_ref().len() as u32
189    }
190}
191
192/// FLV tag decoder.
193#[derive(Debug, Default)]
194pub struct TagDecoder {
195    header: Peekable<TagHeaderDecoder>,
196    data: Length<TagDataDecoder>,
197}
198impl TagDecoder {
199    /// Makes a new `TagDecoder` instance.
200    pub fn new() -> Self {
201        TagDecoder::default()
202    }
203}
204impl Decode for TagDecoder {
205    type Item = Tag;
206
207    fn decode(&mut self, buf: &[u8], eos: Eos) -> Result<usize> {
208        let mut offset = 0;
209        if !self.header.is_idle() {
210            bytecodec_try_decode!(self.header, offset, buf, eos);
211            let header = self.header.peek().expect("Never fails");
212            let data = match header.tag_type {
213                TagKind::Audio => TagDataDecoder::Audio(Default::default()),
214                TagKind::Video => TagDataDecoder::Video(Default::default()),
215                TagKind::ScriptData => TagDataDecoder::ScriptData(Default::default()),
216            };
217            self.data = data.length(u64::from(header.data_size));
218        }
219        bytecodec_try_decode!(self.data, offset, buf, eos);
220        Ok(offset)
221    }
222
223    fn finish_decoding(&mut self) -> Result<Self::Item> {
224        let header = track!(self.header.finish_decoding())?;
225        let data = track!(self.data.finish_decoding())?;
226        let tag = match data {
227            TagData::Audio(d) => Tag::from(AudioTag {
228                timestamp: header.timestamp,
229                stream_id: header.stream_id,
230                sound_format: d.sound_format,
231                sound_rate: d.sound_rate,
232                sound_size: d.sound_size,
233                sound_type: d.sound_type,
234                aac_packet_type: d.aac_packet_type,
235                data: d.data,
236            }),
237            TagData::Video(d) => Tag::from(VideoTag {
238                timestamp: header.timestamp,
239                stream_id: header.stream_id,
240                frame_type: d.frame_type,
241                codec_id: d.codec_id,
242                avc_packet_type: d.avc_packet_type,
243                composition_time: d.composition_time,
244                data: d.data,
245            }),
246            TagData::ScriptData(d) => Tag::from(ScriptDataTag {
247                timestamp: header.timestamp,
248                stream_id: header.stream_id,
249                data: d.data,
250            }),
251        };
252        Ok(tag)
253    }
254
255    fn is_idle(&self) -> bool {
256        self.header.is_idle() && self.data.is_idle()
257    }
258
259    fn requiring_bytes(&self) -> ByteCount {
260        if self.header.is_idle() {
261            self.data.requiring_bytes()
262        } else {
263            self.header.requiring_bytes()
264        }
265    }
266}
267
268#[derive(Debug)]
269struct TagHeader {
270    tag_type: TagKind,
271    data_size: u32, // u24
272    timestamp: Timestamp,
273    stream_id: StreamId,
274}
275impl TagHeader {
276    const SIZE: u32 = 11;
277}
278
279#[derive(Debug, Default)]
280struct TagHeaderDecoder {
281    tag_type: U8Decoder,
282    data_size: U24beDecoder,
283    timestamp: U24beDecoder,
284    timestamp_extended: U8Decoder,
285    stream_id: U24beDecoder,
286}
287impl Decode for TagHeaderDecoder {
288    type Item = TagHeader;
289
290    fn decode(&mut self, buf: &[u8], eos: Eos) -> Result<usize> {
291        let mut offset = 0;
292        bytecodec_try_decode!(self.tag_type, offset, buf, eos);
293        bytecodec_try_decode!(self.data_size, offset, buf, eos);
294        bytecodec_try_decode!(self.timestamp, offset, buf, eos);
295        bytecodec_try_decode!(self.timestamp_extended, offset, buf, eos);
296        bytecodec_try_decode!(self.stream_id, offset, buf, eos);
297        Ok(offset)
298    }
299
300    fn finish_decoding(&mut self) -> Result<Self::Item> {
301        let tag_type = track!(self.tag_type.finish_decoding())?;
302        let data_size = track!(self.data_size.finish_decoding())?;
303        let timestamp = track!(self.timestamp.finish_decoding())?;
304        let timestamp_extended = track!(self.timestamp_extended.finish_decoding())?;
305        let stream_id = track!(self.stream_id.finish_decoding())?;
306
307        let tag_type = match tag_type {
308            TAG_TYPE_AUDIO => TagKind::Audio,
309            TAG_TYPE_VIDEO => TagKind::Video,
310            TAG_TYPE_SCRIPT_DATA => TagKind::ScriptData,
311            _ => track_panic!(
312                ErrorKind::InvalidInput,
313                "Unknown FLV tag type: {}",
314                tag_type
315            ),
316        };
317        track_assert!(
318            data_size <= 0x00FF_FFFF,
319            ErrorKind::InvalidInput,
320            "Too large FLV tag data size: {}",
321            data_size
322        );
323        let timestamp = Timestamp::new((timestamp as i32) | i32::from(timestamp_extended) << 24);
324        Ok(TagHeader {
325            tag_type,
326            data_size,
327            timestamp,
328            stream_id: track!(StreamId::new(stream_id))?,
329        })
330    }
331
332    fn is_idle(&self) -> bool {
333        self.stream_id.is_idle()
334    }
335
336    fn requiring_bytes(&self) -> ByteCount {
337        self.tag_type
338            .requiring_bytes()
339            .add_for_decoding(self.data_size.requiring_bytes())
340            .add_for_decoding(self.timestamp.requiring_bytes())
341            .add_for_decoding(self.timestamp_extended.requiring_bytes())
342            .add_for_decoding(self.stream_id.requiring_bytes())
343    }
344}
345
346#[derive(Debug)]
347enum TagData {
348    Audio(AudioTagData),
349    Video(VideoTagData),
350    ScriptData(ScriptDataTagData),
351}
352
353#[derive(Debug)]
354struct AudioTagData {
355    pub sound_format: SoundFormat,
356    pub sound_rate: SoundRate,
357    pub sound_size: SoundSize,
358    pub sound_type: SoundType,
359    pub aac_packet_type: Option<AacPacketType>,
360    pub data: Vec<u8>,
361}
362
363#[derive(Debug)]
364struct VideoTagData {
365    frame_type: FrameType,
366    codec_id: CodecId,
367    avc_packet_type: Option<AvcPacketType>,
368    composition_time: Option<TimeOffset>,
369    data: Vec<u8>,
370}
371
372#[derive(Debug)]
373struct ScriptDataTagData {
374    data: Vec<u8>,
375}
376
377#[derive(Debug)]
378enum TagDataDecoder {
379    Audio(AudioTagDataDecoder),
380    Video(VideoTagDataDecoder),
381    ScriptData(ScriptDataTagDataDecoder),
382    None,
383}
384impl Decode for TagDataDecoder {
385    type Item = TagData;
386
387    fn decode(&mut self, buf: &[u8], eos: Eos) -> Result<usize> {
388        match self {
389            TagDataDecoder::Audio(d) => track!(d.decode(buf, eos)),
390            TagDataDecoder::Video(d) => track!(d.decode(buf, eos)),
391            TagDataDecoder::ScriptData(d) => track!(d.decode(buf, eos)),
392            TagDataDecoder::None => track_panic!(ErrorKind::InconsistentState),
393        }
394    }
395
396    fn finish_decoding(&mut self) -> Result<Self::Item> {
397        let data = match self {
398            TagDataDecoder::Audio(d) => TagData::Audio(track!(d.finish_decoding())?),
399            TagDataDecoder::Video(d) => TagData::Video(track!(d.finish_decoding())?),
400            TagDataDecoder::ScriptData(d) => TagData::ScriptData(track!(d.finish_decoding())?),
401            TagDataDecoder::None => track_panic!(ErrorKind::InconsistentState),
402        };
403        *self = TagDataDecoder::None;
404        Ok(data)
405    }
406
407    fn is_idle(&self) -> bool {
408        match self {
409            TagDataDecoder::Audio(d) => d.is_idle(),
410            TagDataDecoder::Video(d) => d.is_idle(),
411            TagDataDecoder::ScriptData(d) => d.is_idle(),
412            TagDataDecoder::None => true,
413        }
414    }
415
416    fn requiring_bytes(&self) -> ByteCount {
417        match self {
418            TagDataDecoder::Audio(d) => d.requiring_bytes(),
419            TagDataDecoder::Video(d) => d.requiring_bytes(),
420            TagDataDecoder::ScriptData(d) => d.requiring_bytes(),
421            TagDataDecoder::None => ByteCount::Finite(0),
422        }
423    }
424}
425impl Default for TagDataDecoder {
426    fn default() -> Self {
427        TagDataDecoder::None
428    }
429}
430
431#[derive(Debug, Default)]
432struct AudioTagDataDecoder {
433    header: Peekable<U8Decoder>,
434    aac_packet_type: U8Decoder,
435    data: RemainingBytesDecoder,
436}
437impl AudioTagDataDecoder {
438    fn is_aac_packet(&self) -> bool {
439        self.header.peek().map_or(false, |&b| (b >> 4) == 10)
440    }
441}
442impl Decode for AudioTagDataDecoder {
443    type Item = AudioTagData;
444
445    fn decode(&mut self, buf: &[u8], eos: Eos) -> Result<usize> {
446        let mut offset = 0;
447        bytecodec_try_decode!(self.header, offset, buf, eos);
448        if self.is_aac_packet() {
449            bytecodec_try_decode!(self.aac_packet_type, offset, buf, eos);
450        }
451        bytecodec_try_decode!(self.data, offset, buf, eos);
452        Ok(offset)
453    }
454
455    fn finish_decoding(&mut self) -> Result<Self::Item> {
456        let b = track!(self.header.finish_decoding())?;
457        let sound_format = track!(SoundFormat::from_u8(b >> 4))?;
458        let sound_rate = track!(SoundRate::from_u8((b >> 2) & 0b11))?;
459        let sound_size = SoundSize::from_bool((b & 0b10) != 0);
460        let sound_type = SoundType::from_bool((b & 0b01) != 0);
461
462        let aac_packet_type = if let SoundFormat::Aac = sound_format {
463            let b = track!(self.aac_packet_type.finish_decoding())?;
464            Some(track!(AacPacketType::from_u8(b))?)
465        } else {
466            None
467        };
468
469        let data = track!(self.data.finish_decoding())?;
470        Ok(AudioTagData {
471            sound_format,
472            sound_rate,
473            sound_size,
474            sound_type,
475            aac_packet_type,
476            data,
477        })
478    }
479
480    fn is_idle(&self) -> bool {
481        self.data.is_idle()
482    }
483
484    fn requiring_bytes(&self) -> ByteCount {
485        ByteCount::Unknown
486    }
487}
488
489#[derive(Debug, Default)]
490struct FrameTypeAndCodecDecoder(U8Decoder);
491impl Decode for FrameTypeAndCodecDecoder {
492    type Item = (FrameType, CodecId);
493
494    fn decode(&mut self, buf: &[u8], eos: Eos) -> Result<usize> {
495        track!(self.0.decode(buf, eos))
496    }
497
498    fn finish_decoding(&mut self) -> Result<Self::Item> {
499        let b = track!(self.0.finish_decoding())?;
500        let frame_type = track!(FrameType::from_u8(b >> 4))?;
501        let codec_id = track!(CodecId::from_u8(b & 0b1111))?;
502        Ok((frame_type, codec_id))
503    }
504
505    fn is_idle(&self) -> bool {
506        self.0.is_idle()
507    }
508
509    fn requiring_bytes(&self) -> ByteCount {
510        self.0.requiring_bytes()
511    }
512}
513
514#[derive(Debug, Default)]
515struct VideoTagDataDecoder {
516    frame_type_and_codec: Peekable<FrameTypeAndCodecDecoder>,
517    avc_packet_type: U8Decoder,
518    composition_time: U24beDecoder,
519    data: RemainingBytesDecoder,
520}
521impl VideoTagDataDecoder {
522    fn is_avc_packet(&self) -> bool {
523        self.frame_type_and_codec.peek().map_or(false, |t| {
524            t.0 != FrameType::VideoInfoOrCommandFrame && t.1 == CodecId::Avc
525        })
526    }
527}
528impl Decode for VideoTagDataDecoder {
529    type Item = VideoTagData;
530
531    fn decode(&mut self, buf: &[u8], eos: Eos) -> Result<usize> {
532        let mut offset = 0;
533        bytecodec_try_decode!(self.frame_type_and_codec, offset, buf, eos);
534        if self.is_avc_packet() {
535            bytecodec_try_decode!(self.avc_packet_type, offset, buf, eos);
536            bytecodec_try_decode!(self.composition_time, offset, buf, eos);
537        }
538        bytecodec_try_decode!(self.data, offset, buf, eos);
539        Ok(offset)
540    }
541
542    fn finish_decoding(&mut self) -> Result<Self::Item> {
543        let is_avc_packet = self.is_avc_packet();
544
545        let (frame_type, codec_id) = track!(self.frame_type_and_codec.finish_decoding())?;
546        let avc_packet_type = if is_avc_packet {
547            let avc_packet_type = track!(self.avc_packet_type.finish_decoding())?;
548            let avc_packet_type = track!(AvcPacketType::from_u8(avc_packet_type))?;
549            Some(avc_packet_type)
550        } else {
551            None
552        };
553        let composition_time = if is_avc_packet {
554            let composition_time = track!(self.composition_time.finish_decoding())?;
555            let composition_time = TimeOffset::from_u24(composition_time);
556            Some(composition_time)
557        } else {
558            None
559        };
560        let data = track!(self.data.finish_decoding())?;
561        Ok(VideoTagData {
562            frame_type,
563            codec_id,
564            avc_packet_type,
565            composition_time,
566            data,
567        })
568    }
569
570    fn is_idle(&self) -> bool {
571        self.data.is_idle()
572    }
573
574    fn requiring_bytes(&self) -> ByteCount {
575        ByteCount::Unknown
576    }
577}
578
579#[derive(Debug, Default)]
580struct ScriptDataTagDataDecoder(RemainingBytesDecoder);
581impl Decode for ScriptDataTagDataDecoder {
582    type Item = ScriptDataTagData;
583
584    fn decode(&mut self, buf: &[u8], eos: Eos) -> Result<usize> {
585        track!(self.0.decode(buf, eos))
586    }
587
588    fn finish_decoding(&mut self) -> Result<Self::Item> {
589        let data = track!(self.0.finish_decoding())?;
590        Ok(ScriptDataTagData { data })
591    }
592
593    fn is_idle(&self) -> bool {
594        self.0.is_idle()
595    }
596
597    fn requiring_bytes(&self) -> ByteCount {
598        self.0.requiring_bytes()
599    }
600}
601
602/// FLV tag encoder.
603#[derive(Debug)]
604pub struct TagEncoder<Data> {
605    audio: AudioTagEncoder<Data>,
606    video: VideoTagEncoder<Data>,
607    script_data: ScriptDataTagEncoder<Data>,
608}
609impl<Data> TagEncoder<Data> {
610    /// Makes a new `TagEncoder` instance.
611    pub fn new() -> Self {
612        Self::default()
613    }
614}
615impl<Data: AsRef<[u8]>> Encode for TagEncoder<Data> {
616    type Item = Tag<Data>;
617
618    fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result<usize> {
619        let mut offset = 0;
620        bytecodec_try_encode!(self.audio, offset, buf, eos);
621        bytecodec_try_encode!(self.video, offset, buf, eos);
622        bytecodec_try_encode!(self.script_data, offset, buf, eos);
623        Ok(offset)
624    }
625
626    fn start_encoding(&mut self, item: Self::Item) -> Result<()> {
627        match item {
628            Tag::Audio(t) => track!(self.audio.start_encoding(t)),
629            Tag::Video(t) => track!(self.video.start_encoding(t)),
630            Tag::ScriptData(t) => track!(self.script_data.start_encoding(t)),
631        }
632    }
633
634    fn requiring_bytes(&self) -> ByteCount {
635        ByteCount::Finite(self.exact_requiring_bytes())
636    }
637
638    fn is_idle(&self) -> bool {
639        self.audio.is_idle() && self.video.is_idle() && self.script_data.is_idle()
640    }
641}
642impl<Data: AsRef<[u8]>> SizedEncode for TagEncoder<Data> {
643    fn exact_requiring_bytes(&self) -> u64 {
644        self.audio.exact_requiring_bytes()
645            + self.video.exact_requiring_bytes()
646            + self.script_data.exact_requiring_bytes()
647    }
648}
649impl<Data> Default for TagEncoder<Data> {
650    fn default() -> Self {
651        TagEncoder {
652            audio: AudioTagEncoder::default(),
653            video: VideoTagEncoder::default(),
654            script_data: ScriptDataTagEncoder::default(),
655        }
656    }
657}
658
659#[derive(Debug)]
660struct AudioTagEncoder<Data> {
661    header: TagHeaderEncoder,
662    audio_specific: U8Encoder,
663    aac_specific: U8Encoder,
664    data: BytesEncoder<Data>,
665}
666impl<Data: AsRef<[u8]>> Encode for AudioTagEncoder<Data> {
667    type Item = AudioTag<Data>;
668
669    fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result<usize> {
670        let mut offset = 0;
671        bytecodec_try_encode!(self.header, offset, buf, eos);
672        bytecodec_try_encode!(self.audio_specific, offset, buf, eos);
673        bytecodec_try_encode!(self.aac_specific, offset, buf, eos);
674        bytecodec_try_encode!(self.data, offset, buf, eos);
675        Ok(offset)
676    }
677
678    fn start_encoding(&mut self, item: Self::Item) -> Result<()> {
679        let audio_specific = ((item.sound_format as u8) << 4)
680            | ((item.sound_rate as u8) << 2)
681            | ((item.sound_size as u8) << 1)
682            | (item.sound_type as u8);
683        track!(self.audio_specific.start_encoding(audio_specific))?;
684        if let Some(packet_type) = item.aac_packet_type {
685            track!(self.aac_specific.start_encoding(packet_type as u8))?;
686        }
687        track!(self.data.start_encoding(item.data))?;
688        let data_size = self.audio_specific.exact_requiring_bytes()
689            + self.aac_specific.exact_requiring_bytes()
690            + self.data.exact_requiring_bytes();
691        track_assert!(data_size <= 0xFF_FFFF, ErrorKind::InvalidInput; data_size);
692
693        let header = TagHeader {
694            tag_type: TagKind::Audio,
695            data_size: data_size as u32,
696            timestamp: item.timestamp,
697            stream_id: item.stream_id,
698        };
699        track!(self.header.start_encoding(header))?;
700        Ok(())
701    }
702
703    fn requiring_bytes(&self) -> ByteCount {
704        ByteCount::Finite(self.exact_requiring_bytes())
705    }
706
707    fn is_idle(&self) -> bool {
708        self.header.is_idle()
709            && self.audio_specific.is_idle()
710            && self.aac_specific.is_idle()
711            && self.data.is_idle()
712    }
713}
714impl<Data: AsRef<[u8]>> SizedEncode for AudioTagEncoder<Data> {
715    fn exact_requiring_bytes(&self) -> u64 {
716        self.header.exact_requiring_bytes()
717            + self.audio_specific.exact_requiring_bytes()
718            + self.aac_specific.exact_requiring_bytes()
719            + self.data.exact_requiring_bytes()
720    }
721}
722impl<Data> Default for AudioTagEncoder<Data> {
723    fn default() -> Self {
724        AudioTagEncoder {
725            header: TagHeaderEncoder::default(),
726            audio_specific: U8Encoder::default(),
727            aac_specific: U8Encoder::default(),
728            data: BytesEncoder::default(),
729        }
730    }
731}
732
733#[derive(Debug)]
734struct VideoTagEncoder<Data> {
735    header: TagHeaderEncoder,
736    video_specific: U8Encoder,
737    avc_specific: U32beEncoder,
738    data: BytesEncoder<Data>,
739}
740impl<Data: AsRef<[u8]>> Encode for VideoTagEncoder<Data> {
741    type Item = VideoTag<Data>;
742
743    fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result<usize> {
744        let mut offset = 0;
745        bytecodec_try_encode!(self.header, offset, buf, eos);
746        bytecodec_try_encode!(self.video_specific, offset, buf, eos);
747        bytecodec_try_encode!(self.avc_specific, offset, buf, eos);
748        bytecodec_try_encode!(self.data, offset, buf, eos);
749        Ok(offset)
750    }
751
752    fn start_encoding(&mut self, item: Self::Item) -> Result<()> {
753        let video_specific = ((item.frame_type as u8) << 4) | (item.codec_id as u8);
754        track!(self.video_specific.start_encoding(video_specific))?;
755        if let Some(packet_type) = item.avc_packet_type {
756            let ct = track_assert_some!(item.composition_time, ErrorKind::InvalidInput);
757            let avc_specific = ((packet_type as u32) << 24) | ((ct.value() as u32) & 0xFF_FFFF);
758            track!(self.avc_specific.start_encoding(avc_specific))?;
759        }
760        track!(self.data.start_encoding(item.data))?;
761        let data_size = self.video_specific.exact_requiring_bytes()
762            + self.avc_specific.exact_requiring_bytes()
763            + self.data.exact_requiring_bytes();
764        track_assert!(data_size <= 0xFF_FFFF, ErrorKind::InvalidInput; data_size);
765
766        let header = TagHeader {
767            tag_type: TagKind::Video,
768            data_size: data_size as u32,
769            timestamp: item.timestamp,
770            stream_id: item.stream_id,
771        };
772        track!(self.header.start_encoding(header))?;
773        Ok(())
774    }
775
776    fn requiring_bytes(&self) -> ByteCount {
777        ByteCount::Finite(self.exact_requiring_bytes())
778    }
779
780    fn is_idle(&self) -> bool {
781        self.header.is_idle()
782            && self.video_specific.is_idle()
783            && self.avc_specific.is_idle()
784            && self.data.is_idle()
785    }
786}
787impl<Data: AsRef<[u8]>> SizedEncode for VideoTagEncoder<Data> {
788    fn exact_requiring_bytes(&self) -> u64 {
789        self.header.exact_requiring_bytes()
790            + self.video_specific.exact_requiring_bytes()
791            + self.avc_specific.exact_requiring_bytes()
792            + self.data.exact_requiring_bytes()
793    }
794}
795impl<Data> Default for VideoTagEncoder<Data> {
796    fn default() -> Self {
797        VideoTagEncoder {
798            header: TagHeaderEncoder::default(),
799            video_specific: U8Encoder::default(),
800            avc_specific: U32beEncoder::default(),
801            data: BytesEncoder::default(),
802        }
803    }
804}
805
806#[derive(Debug)]
807struct ScriptDataTagEncoder<Data> {
808    header: TagHeaderEncoder,
809    data: BytesEncoder<Data>,
810}
811impl<Data: AsRef<[u8]>> Encode for ScriptDataTagEncoder<Data> {
812    type Item = ScriptDataTag<Data>;
813
814    fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result<usize> {
815        let mut offset = 0;
816        bytecodec_try_encode!(self.header, offset, buf, eos);
817        bytecodec_try_encode!(self.data, offset, buf, eos);
818        Ok(offset)
819    }
820
821    fn start_encoding(&mut self, item: Self::Item) -> Result<()> {
822        track!(self.data.start_encoding(item.data))?;
823        let data_size = self.data.exact_requiring_bytes();
824        track_assert!(data_size <= 0xFF_FFFF, ErrorKind::InvalidInput; data_size);
825
826        let header = TagHeader {
827            tag_type: TagKind::ScriptData,
828            data_size: data_size as u32,
829            timestamp: item.timestamp,
830            stream_id: item.stream_id,
831        };
832        track!(self.header.start_encoding(header))?;
833        Ok(())
834    }
835
836    fn requiring_bytes(&self) -> ByteCount {
837        ByteCount::Finite(self.exact_requiring_bytes())
838    }
839
840    fn is_idle(&self) -> bool {
841        self.header.is_idle() && self.data.is_idle()
842    }
843}
844impl<Data: AsRef<[u8]>> SizedEncode for ScriptDataTagEncoder<Data> {
845    fn exact_requiring_bytes(&self) -> u64 {
846        self.header.exact_requiring_bytes() + self.data.exact_requiring_bytes()
847    }
848}
849impl<Data> Default for ScriptDataTagEncoder<Data> {
850    fn default() -> Self {
851        ScriptDataTagEncoder {
852            header: TagHeaderEncoder::default(),
853            data: BytesEncoder::default(),
854        }
855    }
856}
857
858#[derive(Debug, Default)]
859struct TagHeaderEncoder {
860    tag_type: U8Encoder,
861    data_size: U24beEncoder,
862    timestamp: U24beEncoder,
863    timestamp_extended: U8Encoder,
864    stream_id: U24beEncoder,
865}
866impl Encode for TagHeaderEncoder {
867    type Item = TagHeader;
868
869    fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result<usize> {
870        let mut offset = 0;
871        bytecodec_try_encode!(self.tag_type, offset, buf, eos);
872        bytecodec_try_encode!(self.data_size, offset, buf, eos);
873        bytecodec_try_encode!(self.timestamp, offset, buf, eos);
874        bytecodec_try_encode!(self.timestamp_extended, offset, buf, eos);
875        bytecodec_try_encode!(self.stream_id, offset, buf, eos);
876        Ok(offset)
877    }
878
879    fn start_encoding(&mut self, item: Self::Item) -> Result<()> {
880        let timestamp = item.timestamp.value() as u32;
881        track!(self.tag_type.start_encoding(item.tag_type as u8))?;
882        track!(self.data_size.start_encoding(item.data_size))?;
883        track!(self.timestamp.start_encoding(timestamp & 0xFF_FFFF))?;
884        track!(
885            self.timestamp_extended
886                .start_encoding((timestamp >> 24) as u8)
887        )?;
888        track!(self.stream_id.start_encoding(item.stream_id.value()))?;
889        Ok(())
890    }
891
892    fn requiring_bytes(&self) -> ByteCount {
893        ByteCount::Finite(self.exact_requiring_bytes())
894    }
895
896    fn is_idle(&self) -> bool {
897        self.tag_type.is_idle()
898            && self.data_size.is_idle()
899            && self.timestamp.is_idle()
900            && self.timestamp_extended.is_idle()
901            && self.stream_id.is_idle()
902    }
903}
904impl SizedEncode for TagHeaderEncoder {
905    fn exact_requiring_bytes(&self) -> u64 {
906        self.tag_type.exact_requiring_bytes()
907            + self.data_size.exact_requiring_bytes()
908            + self.timestamp.exact_requiring_bytes()
909            + self.timestamp_extended.exact_requiring_bytes()
910            + self.stream_id.exact_requiring_bytes()
911    }
912}