@@ -233,6 +233,10 @@ pub struct H264DecoderState<B: StatelessDecoderBackend<Sps>> {
233
233
/// We are not using `DbpEntry<T>` as the type because contrary to a DPB entry,
234
234
/// the handle of this member is always valid.
235
235
last_field : Option < ( Rc < RefCell < PictureData > > , B :: Handle ) > ,
236
+
237
+ /// The picture currently being decoded. We need to preserve it between calls to `decode`
238
+ /// because multiple slices will be processed in different calls to `decode`.
239
+ current_pic : Option < CurrentPicState < B > > ,
236
240
}
237
241
238
242
impl < B > Default for H264DecoderState < B >
@@ -250,10 +254,20 @@ where
250
254
prev_pic_info : Default :: default ( ) ,
251
255
max_long_term_frame_idx : Default :: default ( ) ,
252
256
last_field : Default :: default ( ) ,
257
+ current_pic : None ,
253
258
}
254
259
}
255
260
}
256
261
262
+ /// [`StatelessCodec`] structure to use in order to create a H.264 stateless decoder.
263
+ ///
264
+ /// # Accepted input
265
+ ///
266
+ /// A decoder using this codec processes exactly one NAL unit of input per call to
267
+ /// [`StatelessDecoder::decode`], and returns the number of bytes until the end of this NAL unit.
268
+ /// This makes it possible to call [`Decode`](StatelessDecoder::decode) repeatedly on some unsplit
269
+ /// Annex B stream and shrinking it by the number of bytes processed after each call, until the
270
+ /// stream ends up being empty.
257
271
pub struct H264 ;
258
272
259
273
impl StatelessCodec for H264 {
@@ -617,8 +631,6 @@ where
617
631
max_num_order_frames
618
632
} ;
619
633
620
- self . ready_queue . extend ( self . codec . drain ( ) ) ;
621
-
622
634
self . coded_resolution = resolution;
623
635
624
636
self . codec
@@ -627,6 +639,17 @@ where
627
639
self . codec . dpb . set_interlaced ( interlaced) ;
628
640
}
629
641
642
+ fn drain ( & mut self ) -> anyhow:: Result < ( ) > {
643
+ // Finish the current picture if there is one pending.
644
+ if let Some ( cur_pic) = self . codec . current_pic . take ( ) {
645
+ self . finish_picture ( cur_pic) ?;
646
+ }
647
+
648
+ self . ready_queue . extend ( self . codec . drain ( ) ) ;
649
+
650
+ Ok ( ( ) )
651
+ }
652
+
630
653
fn sort_pic_num_descending ( pics : & mut [ DpbEntry < B :: Handle > ] ) {
631
654
pics. sort_by_key ( |h| std:: cmp:: Reverse ( h. 0 . borrow ( ) . pic_num ) ) ;
632
655
}
@@ -1245,7 +1268,7 @@ where
1245
1268
// Clause 3:
1246
1269
// The current picture has memory_management_control_operation equal
1247
1270
// to 5, as specified in clause C.4.4.
1248
- self . ready_queue . extend ( self . codec . drain ( ) ) ;
1271
+ self . drain ( ) ? ;
1249
1272
}
1250
1273
1251
1274
// Bump the DPB as per C.4.5.3 to cover clauses 1, 4, 5 and 6.
@@ -1418,7 +1441,7 @@ where
1418
1441
// no_output_of_prior_pics_flag is not equal to 1 and is not
1419
1442
// inferred to be equal to 1, as specified in clause C.4.4.
1420
1443
if !pic. ref_pic_marking . no_output_of_prior_pics_flag ( ) {
1421
- self . ready_queue . extend ( self . codec . drain ( ) ) ;
1444
+ self . drain ( ) ? ;
1422
1445
} else {
1423
1446
// C.4.4 When no_output_of_prior_pics_flag is equal to 1 or is
1424
1447
// inferred to be equal to 1, all frame buffers in the DPB are
@@ -1440,7 +1463,11 @@ where
1440
1463
& mut self ,
1441
1464
timestamp : u64 ,
1442
1465
slice : & Slice < & [ u8 ] > ,
1443
- ) -> anyhow:: Result < CurrentPicState < B > > {
1466
+ ) -> Result < CurrentPicState < B > , DecodeError > {
1467
+ if self . backend . surface_pool ( ) . num_free_surfaces ( ) == 0 {
1468
+ return Err ( DecodeError :: NotEnoughOutputBuffers ( 1 ) ) ;
1469
+ }
1470
+
1444
1471
let nalu_hdr = slice. nalu ( ) . header ( ) ;
1445
1472
1446
1473
if nalu_hdr. idr_pic_flag ( ) {
@@ -1793,77 +1820,47 @@ where
1793
1820
Ok ( handle)
1794
1821
}
1795
1822
1796
- fn peek_sps ( parser : & mut Parser , bitstream : & [ u8 ] ) -> Option < Sps > {
1797
- let mut cursor = Cursor :: new ( bitstream) ;
1798
-
1799
- while let Ok ( nalu) = Nalu :: next ( & mut cursor) {
1800
- if matches ! ( nalu. header( ) . nalu_type( ) , NaluType :: Sps ) {
1801
- let sps = parser. parse_sps ( & nalu) . ok ( ) ?;
1802
- return Some ( sps. clone ( ) ) ;
1823
+ fn process_nalu ( & mut self , timestamp : u64 , nalu : Nalu < & [ u8 ] > ) -> Result < ( ) , DecodeError > {
1824
+ match nalu. header ( ) . nalu_type ( ) {
1825
+ NaluType :: Sps => {
1826
+ self . codec . parser . parse_sps ( & nalu) ?;
1803
1827
}
1804
- }
1805
-
1806
- None
1807
- }
1808
-
1809
- fn decode_access_unit ( & mut self , timestamp : u64 , bitstream : & [ u8 ] ) -> Result < ( ) , DecodeError > {
1810
- if self . backend . surface_pool ( ) . num_free_surfaces ( ) == 0 {
1811
- return Err ( DecodeError :: NotEnoughOutputBuffers ( 1 ) ) ;
1812
- }
1813
-
1814
- let mut cursor = Cursor :: new ( bitstream) ;
1815
-
1816
- let mut cur_pic_opt: Option < CurrentPicState < B > > = None ;
1817
-
1818
- while let Ok ( nalu) = Nalu :: next ( & mut cursor) {
1819
- match nalu. header ( ) . nalu_type ( ) {
1820
- NaluType :: Sps => {
1821
- self . codec . parser . parse_sps ( & nalu) ?;
1822
- }
1823
-
1824
- NaluType :: Pps => {
1825
- self . codec . parser . parse_pps ( & nalu) ?;
1826
- }
1827
-
1828
- NaluType :: Slice
1829
- | NaluType :: SliceDpa
1830
- | NaluType :: SliceDpb
1831
- | NaluType :: SliceDpc
1832
- | NaluType :: SliceIdr
1833
- | NaluType :: SliceExt => {
1834
- let slice = self . codec . parser . parse_slice_header ( nalu) ?;
1835
- let mut cur_pic = match cur_pic_opt {
1836
- // No current picture, start a new one.
1837
- None => self . begin_picture ( timestamp, & slice) ?,
1838
- // We have a current picture but are starting a new field, or first_mb_in_slice
1839
- // indicates that a new picture is starting: finish the current picture and
1840
- // start a new one.
1841
- Some ( cur_pic)
1842
- if ( self . codec . dpb . interlaced ( )
1843
- && matches ! ( cur_pic. pic. field, Field :: Frame )
1844
- && !cur_pic. pic . is_second_field ( )
1845
- && cur_pic. pic . field != slice. header ( ) . field ( ) )
1846
- || ( slice. header ( ) . first_mb_in_slice == 0 ) =>
1847
- {
1848
- self . finish_picture ( cur_pic) ?;
1849
- self . begin_picture ( timestamp, & slice) ?
1850
- }
1851
- // This slice is part of the current picture.
1852
- Some ( cur_pic) => cur_pic,
1853
- } ;
1854
-
1855
- self . handle_slice ( & mut cur_pic, & slice) ?;
1856
- cur_pic_opt = Some ( cur_pic) ;
1857
- }
1858
-
1859
- other => {
1860
- debug ! ( "Unsupported NAL unit type {:?}" , other, ) ;
1861
- }
1828
+ NaluType :: Pps => {
1829
+ self . codec . parser . parse_pps ( & nalu) ?;
1862
1830
}
1863
- }
1831
+ NaluType :: Slice
1832
+ | NaluType :: SliceDpa
1833
+ | NaluType :: SliceDpb
1834
+ | NaluType :: SliceDpc
1835
+ | NaluType :: SliceIdr
1836
+ | NaluType :: SliceExt => {
1837
+ let slice = self . codec . parser . parse_slice_header ( nalu) ?;
1838
+ let mut cur_pic = match self . codec . current_pic . take ( ) {
1839
+ // No current picture, start a new one.
1840
+ None => self . begin_picture ( timestamp, & slice) ?,
1841
+ // We have a current picture but are starting a new field, or first_mb_in_slice
1842
+ // indicates that a new picture is starting: finish the current picture and
1843
+ // start a new one.
1844
+ Some ( cur_pic)
1845
+ if ( self . codec . dpb . interlaced ( )
1846
+ && matches ! ( cur_pic. pic. field, Field :: Frame )
1847
+ && !cur_pic. pic . is_second_field ( )
1848
+ && cur_pic. pic . field != slice. header ( ) . field ( ) )
1849
+ || ( slice. header ( ) . first_mb_in_slice == 0 ) =>
1850
+ {
1851
+ self . finish_picture ( cur_pic) ?;
1852
+ self . begin_picture ( timestamp, & slice) ?
1853
+ }
1854
+ // This slice is part of the current picture.
1855
+ Some ( cur_pic) => cur_pic,
1856
+ } ;
1864
1857
1865
- if let Some ( cur_pic) = cur_pic_opt. take ( ) {
1866
- self . finish_picture ( cur_pic) ?;
1858
+ self . handle_slice ( & mut cur_pic, & slice) ?;
1859
+ self . codec . current_pic = Some ( cur_pic) ;
1860
+ }
1861
+ other => {
1862
+ debug ! ( "Unsupported NAL unit type {:?}" , other, ) ;
1863
+ }
1867
1864
}
1868
1865
1869
1866
Ok ( ( ) )
@@ -1876,13 +1873,15 @@ where
1876
1873
B : StatelessH264DecoderBackend ,
1877
1874
B :: Handle : Clone + ' static ,
1878
1875
{
1879
- fn decode ( & mut self , timestamp : u64 , mut bitstream : & [ u8 ] ) -> Result < usize , DecodeError > {
1880
- let sps = Self :: peek_sps ( & mut self . codec . parser , bitstream) ;
1876
+ fn decode ( & mut self , timestamp : u64 , bitstream : & [ u8 ] ) -> Result < usize , DecodeError > {
1877
+ let mut cursor = Cursor :: new ( bitstream) ;
1878
+ let nalu = Nalu :: next ( & mut cursor) ?;
1881
1879
1882
- if let Some ( sps) = sps {
1880
+ if nalu. header ( ) . nalu_type ( ) == NaluType :: Sps {
1881
+ let sps = self . codec . parser . parse_sps ( & nalu) ?. clone ( ) ;
1883
1882
if Self :: negotiation_possible ( & sps, & self . codec . dpb , self . coded_resolution ) {
1884
1883
// Make sure all the frames we decoded so far are in the ready queue.
1885
- self . ready_queue . extend ( self . codec . drain ( ) ) ;
1884
+ self . drain ( ) ? ;
1886
1885
self . backend . new_sequence ( & sps) ?;
1887
1886
self . decoding_state = DecodingState :: AwaitingFormat ( sps) ;
1888
1887
} else if matches ! ( self . decoding_state, DecodingState :: Reset ) {
@@ -1895,28 +1894,29 @@ where
1895
1894
while let Ok ( nalu) = Nalu :: next ( & mut cursor) {
1896
1895
// In the Reset state we can resume decoding from any key frame.
1897
1896
if matches ! ( nalu. header( ) . nalu_type( ) , NaluType :: SliceIdr ) {
1898
- bitstream = & bitstream[ nalu. sc_offset ( ) ..] ;
1899
1897
self . decoding_state = DecodingState :: Decoding ;
1900
1898
break ;
1901
1899
}
1902
1900
}
1903
1901
}
1904
1902
1905
- let frame_len = bitstream . len ( ) ;
1903
+ let nalu_len = nalu . offset ( ) + nalu . size ( ) ;
1906
1904
1907
1905
match & mut self . decoding_state {
1908
1906
// Skip input until we get information from the stream.
1909
1907
DecodingState :: AwaitingStreamInfo | DecodingState :: Reset => ( ) ,
1910
1908
// Ask the client to confirm the format before we can process this.
1911
1909
DecodingState :: AwaitingFormat ( _) => return Err ( DecodeError :: CheckEvents ) ,
1912
- DecodingState :: Decoding => self . decode_access_unit ( timestamp, bitstream) ?,
1913
- } ;
1910
+ DecodingState :: Decoding => {
1911
+ self . process_nalu ( timestamp, nalu) ?;
1912
+ }
1913
+ }
1914
1914
1915
- Ok ( frame_len )
1915
+ Ok ( nalu_len )
1916
1916
}
1917
1917
1918
1918
fn flush ( & mut self ) -> Result < ( ) , DecodeError > {
1919
- self . ready_queue . extend ( self . codec . drain ( ) ) ;
1919
+ self . drain ( ) ? ;
1920
1920
self . decoding_state = DecodingState :: Reset ;
1921
1921
1922
1922
Ok ( ( ) )
0 commit comments