Skip to content

Commit d93ca64

Browse files
lu-zerobarrbrain
authored andcommitted
Factor out the frame data parsing routine
twopass_in() is a function that does too much at the same time: - It initializes the second pass rc. - It provides the user the amount of bytes the same function would like to consume next - It consumes and parses the initial global header, called summary in the code. - It consumes and parses the per-frame information, depending on the configuration either a single per-frame data packet or a variable number of them in a single pass. This patch moves in a separate function and document a little the frame data parsing code.
1 parent e9b6398 commit d93ca64

File tree

1 file changed

+110
-80
lines changed

1 file changed

+110
-80
lines changed

src/rate.rs

Lines changed: 110 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,7 @@ impl RCState {
13621362
Ok(RCFrameMetrics { log_scale_q24, fti, show_frame })
13631363
}
13641364

1365+
// Initialize the rate control for second pass encoding
13651366
pub(crate) fn twopass_init(&mut self) {
13661367
if self.twopass_state == PASS_SINGLE || self.twopass_state == PASS_1 {
13671368
// Initialize the second pass.
@@ -1387,7 +1388,6 @@ impl RCState {
13871388
}
13881389
}
13891390

1390-
13911391
// Parse the rate control summary
13921392
//
13931393
// It returns the amount of data consumed in the process or
@@ -1488,6 +1488,114 @@ impl RCState {
14881488
TWOPASS_HEADER_SZ + frames_needed * TWOPASS_PACKET_SZ
14891489
}
14901490

1491+
// Return the number of frame data packets to be parsed before
1492+
// the encoding process can continue.
1493+
fn twopass_in_frames_needed(&self) -> i32 {
1494+
let mut cur_scale_window_nframes = 0;
1495+
let mut cur_nframes_left = 0;
1496+
for fti in 0..=FRAME_NSUBTYPES {
1497+
cur_scale_window_nframes += self.scale_window_nframes[fti];
1498+
cur_nframes_left += self.nframes_left[fti];
1499+
}
1500+
1501+
(self.reservoir_frame_delay - self.scale_window_ntus)
1502+
.max(0)
1503+
.min(cur_nframes_left - cur_scale_window_nframes)
1504+
}
1505+
// Parse the rate control per-frame data
1506+
//
1507+
// If no buffer is passed return the amount of data it expects
1508+
// to consume next.
1509+
//
1510+
// If a properly sized buffer is passed it returns the amount of data
1511+
// consumed in the process or an empty error on parsing failure.
1512+
fn twopass_parse_frame_data(
1513+
&mut self, maybe_buf: Option<&[u8]>, mut consumed: usize,
1514+
) -> Result<usize, ()> {
1515+
{
1516+
if self.frame_metrics.is_empty() {
1517+
// We're using a whole-file buffer.
1518+
if let Some(buf) = maybe_buf {
1519+
consumed = self.buffer_fill(buf, consumed, TWOPASS_PACKET_SZ);
1520+
if self.pass2_buffer_fill >= TWOPASS_PACKET_SZ {
1521+
self.pass2_buffer_pos = 0;
1522+
// Read metrics for the next frame.
1523+
self.cur_metrics = self.parse_metrics()?;
1524+
// Clear the buffer for the next frame.
1525+
self.pass2_buffer_fill = 0;
1526+
self.pass2_data_ready = true;
1527+
}
1528+
} else {
1529+
return Ok(TWOPASS_PACKET_SZ - self.pass2_buffer_fill);
1530+
}
1531+
} else {
1532+
// We're using a finite buffer.
1533+
let mut cur_scale_window_nframes = 0;
1534+
let mut cur_nframes_left = 0;
1535+
1536+
for fti in 0..=FRAME_NSUBTYPES {
1537+
cur_scale_window_nframes += self.scale_window_nframes[fti];
1538+
cur_nframes_left += self.nframes_left[fti];
1539+
}
1540+
1541+
let mut frames_needed = self.twopass_in_frames_needed();
1542+
while frames_needed > 0 {
1543+
if let Some(buf) = maybe_buf {
1544+
consumed = self.buffer_fill(buf, consumed, TWOPASS_PACKET_SZ);
1545+
if self.pass2_buffer_fill >= TWOPASS_PACKET_SZ {
1546+
self.pass2_buffer_pos = 0;
1547+
// Read the metrics for the next frame.
1548+
let m = self.parse_metrics()?;
1549+
// Add them to the circular buffer.
1550+
if self.nframe_metrics >= self.frame_metrics.len() {
1551+
// We read too many frames without finding enough TUs.
1552+
return Err(());
1553+
}
1554+
let mut fmi = self.frame_metrics_head + self.nframe_metrics;
1555+
if fmi >= self.frame_metrics.len() {
1556+
fmi -= self.frame_metrics.len();
1557+
}
1558+
self.nframe_metrics += 1;
1559+
self.frame_metrics[fmi] = m;
1560+
// And accumulate the statistics over the window.
1561+
self.scale_window_nframes[m.fti] += 1;
1562+
cur_scale_window_nframes += 1;
1563+
if m.fti < FRAME_NSUBTYPES {
1564+
self.scale_window_sum[m.fti] += bexp_q24(m.log_scale_q24);
1565+
}
1566+
if m.show_frame {
1567+
self.scale_window_ntus += 1;
1568+
}
1569+
frames_needed = (self.reservoir_frame_delay
1570+
- self.scale_window_ntus)
1571+
.max(0)
1572+
.min(cur_nframes_left - cur_scale_window_nframes);
1573+
// Clear the buffer for the next frame.
1574+
self.pass2_buffer_fill = 0;
1575+
} else {
1576+
// Go back for more data.
1577+
break;
1578+
}
1579+
} else {
1580+
return Ok(
1581+
TWOPASS_PACKET_SZ * (frames_needed as usize)
1582+
- self.pass2_buffer_fill,
1583+
);
1584+
}
1585+
}
1586+
// If we've got all the frames we need, fill in the current metrics.
1587+
// We're ready to go.
1588+
if frames_needed <= 0 {
1589+
self.cur_metrics = self.frame_metrics[self.frame_metrics_head];
1590+
// Mark us ready for the next frame.
1591+
self.pass2_data_ready = true;
1592+
}
1593+
}
1594+
}
1595+
1596+
Ok(consumed)
1597+
}
1598+
14911599
// If called without a buffer it will return the size of the next
14921600
// buffer it expects.
14931601
//
@@ -1516,85 +1624,7 @@ impl RCState {
15161624
// to allow any more frames to be encoded.
15171625
self.pass2_data_ready = false;
15181626
} else if !self.pass2_data_ready {
1519-
if self.frame_metrics.is_empty() {
1520-
// We're using a whole-file buffer.
1521-
if let Some(buf) = maybe_buf {
1522-
consumed = self.buffer_fill(buf, consumed, TWOPASS_PACKET_SZ);
1523-
if self.pass2_buffer_fill >= TWOPASS_PACKET_SZ {
1524-
self.pass2_buffer_pos = 0;
1525-
// Read metrics for the next frame.
1526-
self.cur_metrics = self.parse_metrics()?;
1527-
// Clear the buffer for the next frame.
1528-
self.pass2_buffer_fill = 0;
1529-
self.pass2_data_ready = true;
1530-
}
1531-
} else {
1532-
return Ok(TWOPASS_PACKET_SZ - self.pass2_buffer_fill);
1533-
}
1534-
} else {
1535-
// We're using a finite buffer.
1536-
let mut cur_scale_window_nframes = 0;
1537-
let mut cur_nframes_left = 0;
1538-
for fti in 0..=FRAME_NSUBTYPES {
1539-
cur_scale_window_nframes += self.scale_window_nframes[fti];
1540-
cur_nframes_left += self.nframes_left[fti];
1541-
}
1542-
let mut frames_needed = (self.reservoir_frame_delay
1543-
- self.scale_window_ntus)
1544-
.max(0)
1545-
.min(cur_nframes_left - cur_scale_window_nframes);
1546-
while frames_needed > 0 {
1547-
if let Some(buf) = maybe_buf {
1548-
consumed = self.buffer_fill(buf, consumed, TWOPASS_PACKET_SZ);
1549-
if self.pass2_buffer_fill >= TWOPASS_PACKET_SZ {
1550-
self.pass2_buffer_pos = 0;
1551-
// Read the metrics for the next frame.
1552-
let m = self.parse_metrics()?;
1553-
// Add them to the circular buffer.
1554-
if self.nframe_metrics >= self.frame_metrics.len() {
1555-
// We read too many frames without finding enough TUs.
1556-
return Err(());
1557-
}
1558-
let mut fmi = self.frame_metrics_head + self.nframe_metrics;
1559-
if fmi >= self.frame_metrics.len() {
1560-
fmi -= self.frame_metrics.len();
1561-
}
1562-
self.nframe_metrics += 1;
1563-
self.frame_metrics[fmi] = m;
1564-
// And accumulate the statistics over the window.
1565-
self.scale_window_nframes[m.fti] += 1;
1566-
cur_scale_window_nframes += 1;
1567-
if m.fti < FRAME_NSUBTYPES {
1568-
self.scale_window_sum[m.fti] += bexp_q24(m.log_scale_q24);
1569-
}
1570-
if m.show_frame {
1571-
self.scale_window_ntus += 1;
1572-
}
1573-
frames_needed = (self.reservoir_frame_delay
1574-
- self.scale_window_ntus)
1575-
.max(0)
1576-
.min(cur_nframes_left - cur_scale_window_nframes);
1577-
// Clear the buffer for the next frame.
1578-
self.pass2_buffer_fill = 0;
1579-
} else {
1580-
// Go back for more data.
1581-
break;
1582-
}
1583-
} else {
1584-
return Ok(
1585-
TWOPASS_PACKET_SZ * (frames_needed as usize)
1586-
- self.pass2_buffer_fill,
1587-
);
1588-
}
1589-
}
1590-
// If we've got all the frames we need, fill in the current metrics.
1591-
// We're ready to go.
1592-
if frames_needed <= 0 {
1593-
self.cur_metrics = self.frame_metrics[self.frame_metrics_head];
1594-
// Mark us ready for the next frame.
1595-
self.pass2_data_ready = true;
1596-
}
1597-
}
1627+
return self.twopass_parse_frame_data(maybe_buf, consumed);
15981628
}
15991629
}
16001630
Ok(consumed)

0 commit comments

Comments
 (0)