xref: /xiu/library/container/flv/src/demuxer.rs (revision 13bac29a)
1 use crate::{
2     flv_tag_header::{AudioTagHeader, VideoTagHeader},
3     Unmarshal,
4 };
5 
6 use {
7     super::{
8         define::{aac_packet_type, avc_packet_type, tag_type, AvcCodecId, FlvData, SoundFormat},
9         errors::FlvDemuxerError,
10         mpeg4_aac::Mpeg4AacProcessor,
11         mpeg4_avc::Mpeg4AvcProcessor,
12     },
13     byteorder::BigEndian,
14     bytes::BytesMut,
15     bytesio::bytes_reader::BytesReader,
16 };
17 
18 /*
19  ** Flv Struct **
20  +-------------------------------------------------------------------------------+
21  | FLV header(9 bytes) | FLV body                                                |
22  +-------------------------------------------------------------------------------+
23  |                     | PreviousTagSize0(4 bytes)| Tag1|PreviousTagSize1|Tag2|...
24  +-------------------------------------------------------------------------------+
25 
26  *** Flv Tag ***
27  +-------------------------------------------------------------------------------------------------------------------------------+
28  |                                                    Tag1                                                                       |
29  +-------------------------------------------------------------------------------------------------------------------------------+
30  |     Tag Header                                                                                                   |  Tag Data  |
31  +-------------------------------------------------------------------------------------------------------------------------------+
32  | Tag Type(1 byte) | Data Size(3 bytes) | Timestamp(3 bytes dts) | Timestamp Extended(1 byte) | Stream ID(3 bytes) |  Tag Data  |
33  +-------------------------------------------------------------------------------------------------------------------------------+
34 
35 
36   The Tag Data contains
37   - video tag data
38   - audio tag data
39 
40  **** Video Tag ****
41  +-------------------------------------------------+
42  |    Tag Data  (Video Tag)                        |
43  +-------------------------------------------------+
44  | FrameType(4 bits) | CodecID(4 bits) | Video Data|
45  +-------------------------------------------------+
46 
47   The contents of Video Data depends on the codecID:
48   2: H263VIDEOPACKET
49   3: SCREENVIDEOPACKET
50   4: VP6FLVVIDEOPACKET
51   5: VP6FLVALPHAVIDEOPACKET
52   6: SCREENV2VIDEOPACKET
53   7: AVCVIDEOPACKE
54 
55  When the codecid equals 7, the Video Data's struct is as follows:
56 
57  +------------------------------------------------------------+
58  |    Video Data  (codecID == 7)                              |
59  +------------------------------------------------------------+
60  | AVCPacketType(1 byte) | CompositionTime(3 bytes) | Payload |
61  +------------------------------------------------------------+
62 
63  **** Audio Tag ****
64  +----------------------------------------------------------------------------------------+
65  |    Tag Data  (Audio Tag)                                                               |
66  +----------------------------------------------------------------------------------------+
67  | SoundFormat(4 bits) | SoundRate(2 bits) | SoundSize(1 bit) | SoundType(1 bit)| Payload |
68  +----------------------------------------------------------------------------------------+
69 
70  reference: https://www.cnblogs.com/chyingp/p/flv-getting-started.html
71 */
72 
73 #[derive(Default)]
74 pub struct FlvDemuxerAudioData {
75     pub has_data: bool,
76     pub sound_format: u8,
77     pub dts: i64,
78     pub pts: i64,
79     pub data: BytesMut,
80 }
81 
82 impl FlvDemuxerAudioData {
new() -> Self83     pub fn new() -> Self {
84         Self {
85             has_data: false,
86             sound_format: 0,
87             dts: 0,
88             pts: 0,
89             data: BytesMut::new(),
90         }
91     }
92 }
93 #[derive(Default)]
94 pub struct FlvDemuxerVideoData {
95     pub frame_type: u8,
96     pub codec_id: u8,
97     pub dts: i64,
98     pub pts: i64,
99     pub data: BytesMut,
100 }
101 
102 impl FlvDemuxerVideoData {
new() -> Self103     pub fn new() -> Self {
104         Self {
105             codec_id: 0,
106             dts: 0,
107             pts: 0,
108             frame_type: 0,
109             data: BytesMut::new(),
110         }
111     }
112 }
113 
114 #[derive(Default)]
115 pub struct FlvVideoTagDemuxer {
116     avc_processor: Mpeg4AvcProcessor,
117 }
118 
119 impl FlvVideoTagDemuxer {
new() -> Self120     pub fn new() -> Self {
121         Self {
122             avc_processor: Mpeg4AvcProcessor::new(),
123         }
124     }
demux( &mut self, timestamp: u32, data: BytesMut, ) -> Result<Option<FlvDemuxerVideoData>, FlvDemuxerError>125     pub fn demux(
126         &mut self,
127         timestamp: u32,
128         data: BytesMut,
129     ) -> Result<Option<FlvDemuxerVideoData>, FlvDemuxerError> {
130         let mut reader = BytesReader::new(data);
131 
132         let tag_header = VideoTagHeader::unmarshal(&mut reader)?;
133         if tag_header.codec_id == AvcCodecId::H264 as u8 {
134             match tag_header.avc_packet_type {
135                 avc_packet_type::AVC_SEQHDR => {
136                     self.avc_processor
137                         .decoder_configuration_record_load(&mut reader)?;
138 
139                     return Ok(None);
140                 }
141                 avc_packet_type::AVC_NALU => {
142                     let data = self.avc_processor.h264_mp4toannexb(&mut reader)?;
143 
144                     let video_data = FlvDemuxerVideoData {
145                         codec_id: AvcCodecId::H264 as u8,
146                         pts: timestamp as i64 + tag_header.composition_time as i64,
147                         dts: timestamp as i64,
148                         frame_type: tag_header.frame_type,
149                         data,
150                     };
151                     //print!("flv demux video payload length {}\n", video_data.data.len());
152                     return Ok(Some(video_data));
153                 }
154                 _ => {}
155             }
156         }
157 
158         Ok(None)
159     }
160 }
161 
162 #[derive(Default)]
163 pub struct FlvAudioTagDemuxer {
164     aac_processor: Mpeg4AacProcessor,
165 }
166 
167 impl FlvAudioTagDemuxer {
new() -> Self168     pub fn new() -> Self {
169         Self {
170             aac_processor: Mpeg4AacProcessor::new(),
171         }
172     }
173 
demux( &mut self, timestamp: u32, data: BytesMut, ) -> Result<FlvDemuxerAudioData, FlvDemuxerError>174     pub fn demux(
175         &mut self,
176         timestamp: u32,
177         data: BytesMut,
178     ) -> Result<FlvDemuxerAudioData, FlvDemuxerError> {
179         let mut reader = BytesReader::new(data);
180 
181         let tag_header = AudioTagHeader::unmarshal(&mut reader)?;
182         self.aac_processor
183             .extend_data(reader.extract_remaining_bytes());
184 
185         if tag_header.sound_format == SoundFormat::AAC as u8 {
186             match tag_header.aac_packet_type {
187                 aac_packet_type::AAC_SEQHDR => {
188                     self.aac_processor.audio_specific_config_load()?;
189                     return Ok(FlvDemuxerAudioData::new());
190                 }
191                 aac_packet_type::AAC_RAW => {
192                     self.aac_processor.adts_save()?;
193 
194                     let audio_data = FlvDemuxerAudioData {
195                         has_data: true,
196                         sound_format: tag_header.sound_format,
197                         pts: timestamp as i64,
198                         dts: timestamp as i64,
199                         data: self.aac_processor.bytes_writer.extract_current_bytes(),
200                     };
201                     //print!("flv demux audio payload length {}\n", audio_data.data.len());
202                     return Ok(audio_data);
203                 }
204                 _ => {}
205             }
206         }
207 
208         Ok(FlvDemuxerAudioData::new())
209     }
210 }
211 
212 pub struct FlvDemuxer {
213     bytes_reader: BytesReader,
214 }
215 
216 impl FlvDemuxer {
new(data: BytesMut) -> Self217     pub fn new(data: BytesMut) -> Self {
218         Self {
219             bytes_reader: BytesReader::new(data),
220         }
221     }
222 
read_flv_header(&mut self) -> Result<(), FlvDemuxerError>223     pub fn read_flv_header(&mut self) -> Result<(), FlvDemuxerError> {
224         /*flv header*/
225         self.bytes_reader.read_bytes(9)?;
226         Ok(())
227     }
228 
read_flv_tag(&mut self) -> Result<Option<FlvData>, FlvDemuxerError>229     pub fn read_flv_tag(&mut self) -> Result<Option<FlvData>, FlvDemuxerError> {
230         /*previous_tag_size*/
231         self.bytes_reader.read_u32::<BigEndian>()?;
232 
233         /*tag type*/
234         let tag_type = self.bytes_reader.read_u8()?;
235         /*data size*/
236         let data_size = self.bytes_reader.read_u24::<BigEndian>()?;
237         /*timestamp*/
238         let timestamp = self.bytes_reader.read_u24::<BigEndian>()?;
239         /*timestamp extended*/
240         let timestamp_ext = self.bytes_reader.read_u8()?;
241         /*stream id*/
242         self.bytes_reader.read_u24::<BigEndian>()?;
243 
244         let dts: u32 = (timestamp & 0xffffff) | ((timestamp_ext as u32) << 24);
245 
246         /*data*/
247         let body = self.bytes_reader.read_bytes(data_size as usize)?;
248 
249         match tag_type {
250             tag_type::VIDEO => {
251                 return Ok(Some(FlvData::Video {
252                     timestamp: dts,
253                     data: body,
254                 }));
255             }
256             tag_type::AUDIO => {
257                 return Ok(Some(FlvData::Audio {
258                     timestamp: dts,
259                     data: body,
260                 }));
261             }
262 
263             _ => {}
264         }
265 
266         Ok(None)
267     }
268 }
269