1use anyhow::{Context as _, Error, format_err};
6use fidl::endpoints::ClientEnd;
7use fidl_fuchsia_media::*;
8use fidl_fuchsia_mediacodec::*;
9use fidl_fuchsia_sysmem2::*;
10use fuchsia_stream_processors::*;
11use fuchsia_sync::{Mutex, RwLock};
12use futures::future::{MaybeDone, maybe_done};
13use futures::io::{self, AsyncWrite};
14use futures::stream::{FusedStream, Stream};
15use futures::task::{Context, Poll, Waker};
16use futures::{Future, StreamExt, ready};
17use log::{trace, warn};
18use std::collections::{HashSet, VecDeque};
19use std::mem;
20use std::pin::Pin;
21use std::sync::Arc;
22use zx::StatusExt;
23
24use crate::buffer_collection_constraints::buffer_collection_constraints_default;
25use crate::sysmem_allocator::{BufferName, SysmemAllocatedBuffers, SysmemAllocation};
26
27fn fidl_error_to_io_error(e: fidl::Error) -> io::Error {
28 io::Error::other(format_err!("Fidl Error: {}", e))
29}
30
31#[derive(Debug)]
32enum Listener {
35 None,
37 New,
39 Some(Waker),
41}
42
43impl Listener {
44 fn register(&mut self, waker: Waker) {
47 *self = match mem::replace(self, Listener::None) {
48 Listener::None => panic!("Polled a listener with no pollers"),
49 _ => Listener::Some(waker),
50 };
51 }
52
53 fn wake(&mut self) {
56 if let Listener::None = self {
57 return;
58 }
59 match mem::replace(self, Listener::New) {
60 Listener::None => panic!("Should have been polled"),
61 Listener::Some(waker) => waker.wake(),
62 Listener::New => {}
63 }
64 }
65
66 fn waker(&self) -> Option<&Waker> {
68 if let Listener::Some(waker) = self { Some(waker) } else { None }
69 }
70}
71
72impl Default for Listener {
73 fn default() -> Self {
74 Listener::None
75 }
76}
77
78struct OutputQueue {
80 listener: Listener,
82 queue: VecDeque<Packet>,
84 ended: bool,
87}
88
89impl OutputQueue {
90 fn enqueue(&mut self, packet: Packet) {
92 self.queue.push_back(packet);
93 self.listener.wake();
94 }
95
96 fn mark_ended(&mut self) {
99 self.ended = true;
100 self.listener.wake();
101 }
102
103 fn waker(&self) -> Option<&Waker> {
104 self.listener.waker()
105 }
106
107 fn wake(&mut self) {
109 self.listener.wake();
110 }
111}
112
113impl Default for OutputQueue {
114 fn default() -> Self {
115 OutputQueue { listener: Listener::default(), queue: VecDeque::new(), ended: false }
116 }
117}
118
119impl Stream for OutputQueue {
120 type Item = Packet;
121
122 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
123 match self.queue.pop_front() {
124 Some(packet) => Poll::Ready(Some(packet)),
125 None if self.ended => Poll::Ready(None),
126 None => {
127 self.listener.register(cx.waker().clone());
128 Poll::Pending
129 }
130 }
131 }
132}
133
134const MIN_INPUT_BUFFER_SIZE: u32 = 4096;
137const DEFAULT_MIN_OUTPUT_BUFFER_SIZE: u32 = 0;
139const CVSD_MIN_OUTPUT_BUFFER_SIZE: u32 = 60;
144
145#[derive(PartialEq, Eq, Hash, Clone, Debug)]
147struct InputBufferIndex(u32);
148
149struct StreamProcessorInner {
152 processor: StreamProcessorProxy,
154 sysmem_client: AllocatorProxy,
156 events: StreamProcessorEventStream,
158 input_packet_size: u64,
160 client_owned: HashSet<InputBufferIndex>,
163 input_cursor: Option<(InputBufferIndex, u64)>,
165 output_queue: Mutex<OutputQueue>,
169 input_waker: Option<Waker>,
171 input_allocation: MaybeDone<SysmemAllocation>,
173 output_allocation: MaybeDone<SysmemAllocation>,
175 min_output_buffer_size: u32,
177}
178
179impl StreamProcessorInner {
180 fn handle_event(&mut self, evt: StreamProcessorEvent) -> Result<(), Error> {
184 match evt {
185 StreamProcessorEvent::OnInputConstraints { input_constraints } => {
186 let _input_constraints = ValidStreamBufferConstraints::try_from(input_constraints)?;
187 let buffer_constraints =
188 Self::buffer_constraints_from_min_size(MIN_INPUT_BUFFER_SIZE);
189 let processor = self.processor.clone();
190 let mut partial_settings = Self::partial_settings();
191 let token_fn = move |token: ClientEnd<BufferCollectionTokenMarker>| {
192 partial_settings.sysmem_token =
195 Some(ClientEnd::<fidl_fuchsia_sysmem::BufferCollectionTokenMarker>::new(
196 token.into_channel(),
197 ));
198 if let Err(e) = processor.set_input_buffer_partial_settings(partial_settings) {
200 warn!("Couldn't set input buffer settings: {:?}", e);
201 }
202 };
203 self.input_allocation = maybe_done(SysmemAllocation::allocate(
204 self.sysmem_client.clone(),
205 BufferName { name: "StreamProcessorInput", priority: 1 },
206 None,
207 buffer_constraints,
208 token_fn,
209 )?);
210 }
211 StreamProcessorEvent::OnOutputConstraints { output_config } => {
212 let output_constraints = ValidStreamOutputConstraints::try_from(output_config)?;
213 if !output_constraints.buffer_constraints_action_required {
214 return Ok(());
215 }
216 let buffer_constraints =
217 Self::buffer_constraints_from_min_size(self.min_output_buffer_size);
218 let processor = self.processor.clone();
219 let mut partial_settings = Self::partial_settings();
220 let token_fn = move |token: ClientEnd<BufferCollectionTokenMarker>| {
221 partial_settings.sysmem_token =
224 Some(ClientEnd::<fidl_fuchsia_sysmem::BufferCollectionTokenMarker>::new(
225 token.into_channel(),
226 ));
227 if let Err(e) = processor.set_output_buffer_partial_settings(partial_settings) {
229 warn!("Couldn't set output buffer settings: {:?}", e);
230 }
231 };
232
233 self.output_allocation = maybe_done(SysmemAllocation::allocate(
234 self.sysmem_client.clone(),
235 BufferName { name: "StreamProcessorOutput", priority: 1 },
236 None,
237 buffer_constraints,
238 token_fn,
239 )?);
240 }
241 StreamProcessorEvent::OnOutputPacket { output_packet, .. } => {
242 let mut lock = self.output_queue.lock();
243 lock.enqueue(output_packet);
244 }
245 StreamProcessorEvent::OnFreeInputPacket {
246 free_input_packet: PacketHeader { packet_index: Some(idx), .. },
247 } => {
248 if !self.client_owned.insert(InputBufferIndex(idx)) {
249 warn!("Freed an input packet that was already freed: {:?}", idx);
250 }
251 self.setup_input_cursor();
252 }
253 StreamProcessorEvent::OnOutputEndOfStream { .. } => {
254 let mut lock = self.output_queue.lock();
255 lock.mark_ended();
256 }
257 StreamProcessorEvent::OnOutputFormat { .. } => {}
258 e => trace!("Unhandled stream processor event: {:?}", e),
259 }
260 Ok(())
261 }
262
263 fn process_event(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
267 match ready!(self.events.poll_next_unpin(cx)) {
268 Some(Err(e)) => Poll::Ready(Err(e.into())),
269 Some(Ok(event)) => Poll::Ready(self.handle_event(event)),
270 None => Poll::Ready(Err(format_err!("Client disconnected"))),
271 }
272 }
273
274 fn buffer_constraints_from_min_size(min_buffer_size: u32) -> BufferCollectionConstraints {
275 BufferCollectionConstraints {
276 buffer_memory_constraints: Some(BufferMemoryConstraints {
277 min_size_bytes: Some(min_buffer_size as u64),
278 ..Default::default()
279 }),
280 ..buffer_collection_constraints_default()
281 }
282 }
283
284 fn partial_settings() -> StreamBufferPartialSettings {
285 StreamBufferPartialSettings {
286 buffer_lifetime_ordinal: Some(1),
287 buffer_constraints_version_ordinal: Some(1),
288 sysmem_token: None,
289 ..Default::default()
290 }
291 }
292
293 fn input_buffers(&mut self) -> &mut SysmemAllocatedBuffers {
294 Pin::new(&mut self.input_allocation)
295 .output_mut()
296 .expect("allocation completed")
297 .as_mut()
298 .expect("succcessful allocation")
299 }
300
301 fn output_buffers(&mut self) -> &mut SysmemAllocatedBuffers {
302 Pin::new(&mut self.output_allocation)
303 .output_mut()
304 .expect("allocation completed")
305 .as_mut()
306 .expect("succcessful allocation")
307 }
308
309 fn input_allocation_complete(&mut self) -> Result<(), Error> {
312 let _ = Pin::new(&mut self.input_allocation)
313 .output_mut()
314 .ok_or_else(|| format_err!("allocation isn't complete"))?;
315
316 let settings = self.input_buffers().settings();
317 self.input_packet_size = (*settings.size_bytes.as_ref().unwrap()).try_into()?;
318 let buffer_count = self.input_buffers().len();
319 for i in 0..buffer_count {
320 let _ = self.client_owned.insert(InputBufferIndex(i.try_into()?));
321 }
322 self.setup_input_cursor();
324 Ok(())
325 }
326
327 fn output_allocation_complete(&mut self) -> Result<(), Error> {
331 let _ = Pin::new(&mut self.output_allocation)
332 .output_mut()
333 .ok_or_else(|| format_err!("allocation isn't complete"))?;
334 self.processor
335 .complete_output_buffer_partial_settings(1)
336 .context("setting output buffer settings")?;
337 Ok(())
338 }
339
340 fn poll_buffer_allocation(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
343 if let MaybeDone::Future(_) = self.input_allocation {
344 match Pin::new(&mut self.input_allocation).poll(cx) {
345 Poll::Ready(()) => {
346 if let Err(e) = self.input_allocation_complete() {
347 return Poll::Ready(Err(e));
348 }
349 }
350 Poll::Pending => {}
351 };
352 }
353 if let MaybeDone::Future(_) = self.output_allocation {
354 match Pin::new(&mut self.output_allocation).poll(cx) {
355 Poll::Ready(()) => {
356 if let Err(e) = self.output_allocation_complete() {
357 return Poll::Ready(Err(e));
358 }
359 }
360 Poll::Pending => {}
361 };
362 }
363 Poll::Pending
364 }
365
366 fn waiting_waker(&self) -> Option<Waker> {
368 match (self.output_queue.lock().waker(), &self.input_waker) {
369 (None, None) => None,
371 (Some(waker), _) => Some(waker.clone()),
372 (_, Some(waker)) => Some(waker.clone()),
373 }
374 }
375
376 fn poll_events(&mut self) -> Result<(), Error> {
380 let waker = loop {
381 let waker = match self.waiting_waker() {
382 None => return Ok(()),
385 Some(waker) => waker,
386 };
387 match self.process_event(&mut Context::from_waker(&waker)) {
388 Poll::Pending => break waker,
389 Poll::Ready(Err(e)) => {
390 warn!("Stream processing error: {:?}", e);
391 return Err(e.into());
392 }
393 Poll::Ready(Ok(())) => {}
395 }
396 };
397
398 if let Poll::Ready(Err(e)) = self.poll_buffer_allocation(&mut Context::from_waker(&waker)) {
399 warn!("Stream buffer allocation error: {:?}", e);
400 return Err(e.into());
401 }
402 Ok(())
403 }
404
405 fn wake_output(&mut self) {
406 self.output_queue.lock().wake();
407 }
408
409 fn wake_input(&mut self) {
410 if let Some(w) = self.input_waker.take() {
411 w.wake();
412 }
413 }
414
415 fn setup_input_cursor(&mut self) {
418 if self.input_cursor.is_some() {
419 return;
421 }
422 let next_idx = match self.client_owned.iter().next() {
423 None => return,
424 Some(idx) => idx.clone(),
425 };
426 let _ = self.client_owned.remove(&next_idx);
427 self.input_cursor = Some((next_idx, 0));
428 self.wake_input();
429 }
430
431 fn read_output_packet(&mut self, packet: Packet) -> Result<Vec<u8>, Error> {
434 let packet = ValidPacket::try_from(packet)?;
435
436 let output_size = packet.valid_length_bytes as usize;
437 let offset = packet.start_offset as u64;
438 let mut output = vec![0; output_size];
439 let buf_idx = packet.buffer_index;
440 let vmo = self.output_buffers().get_mut(buf_idx).expect("output vmo should exist");
441 vmo.read(&mut output, offset)?;
442 self.processor.recycle_output_packet(&packet.header.into())?;
443 Ok(output)
444 }
445}
446
447pub struct StreamProcessor {
452 inner: Arc<RwLock<StreamProcessorInner>>,
453}
454
455pub struct StreamProcessorOutputStream {
458 inner: Arc<RwLock<StreamProcessorInner>>,
459}
460
461impl StreamProcessor {
462 fn create(
465 processor: StreamProcessorProxy,
466 sysmem_client: AllocatorProxy,
467 min_output_buffer_size: u32,
468 ) -> Self {
469 let events = processor.take_event_stream();
470 Self {
471 inner: Arc::new(RwLock::new(StreamProcessorInner {
472 processor,
473 sysmem_client,
474 events,
475 input_packet_size: 0,
476 client_owned: HashSet::new(),
477 input_cursor: None,
478 output_queue: Default::default(),
479 input_waker: None,
480 input_allocation: maybe_done(SysmemAllocation::pending()),
481 output_allocation: maybe_done(SysmemAllocation::pending()),
482 min_output_buffer_size,
483 })),
484 }
485 }
486
487 pub fn create_encoder(
491 input_domain: DomainFormat,
492 encoder_settings: EncoderSettings,
493 ) -> Result<StreamProcessor, Error> {
494 let sysmem_client = fuchsia_component::client::connect_to_protocol::<AllocatorMarker>()
495 .context("Connecting to sysmem")?;
496
497 let min_output_buffer_size = match &encoder_settings {
498 EncoderSettings::Cvsd(_) => CVSD_MIN_OUTPUT_BUFFER_SIZE,
499 _ => DEFAULT_MIN_OUTPUT_BUFFER_SIZE,
500 };
501
502 let format_details = FormatDetails {
503 domain: Some(input_domain),
504 encoder_settings: Some(encoder_settings),
505 format_details_version_ordinal: Some(1),
506 mime_type: Some("audio/pcm".to_string()),
507 oob_bytes: None,
508 pass_through_parameters: None,
509 timebase: None,
510 ..Default::default()
511 };
512
513 let encoder_params = CreateEncoderParams {
514 input_details: Some(format_details),
515 require_hw: Some(false),
516 ..Default::default()
517 };
518
519 let codec_svc = fuchsia_component::client::connect_to_protocol::<CodecFactoryMarker>()
520 .context("Failed to connect to Codec Factory")?;
521
522 let (processor, stream_processor_serverend) = fidl::endpoints::create_proxy();
523
524 codec_svc.create_encoder(&encoder_params, stream_processor_serverend)?;
525
526 Ok(StreamProcessor::create(processor, sysmem_client, min_output_buffer_size))
527 }
528
529 pub fn create_decoder(
533 mime_type: &str,
534 oob_bytes: Option<Vec<u8>>,
535 ) -> Result<StreamProcessor, Error> {
536 let sysmem_client = fuchsia_component::client::connect_to_protocol::<AllocatorMarker>()
537 .context("Connecting to sysmem")?;
538
539 let format_details = FormatDetails {
540 mime_type: Some(mime_type.to_string()),
541 oob_bytes: oob_bytes,
542 format_details_version_ordinal: Some(1),
543 encoder_settings: None,
544 domain: None,
545 pass_through_parameters: None,
546 timebase: None,
547 ..Default::default()
548 };
549
550 let decoder_params = CreateDecoderParams {
551 input_details: Some(format_details),
552 permit_lack_of_split_header_handling: Some(true),
553 ..Default::default()
554 };
555
556 let codec_svc = fuchsia_component::client::connect_to_protocol::<CodecFactoryMarker>()
557 .context("Failed to connect to Codec Factory")?;
558
559 let (processor, stream_processor_serverend) = fidl::endpoints::create_proxy();
560
561 codec_svc.create_decoder(&decoder_params, stream_processor_serverend)?;
562
563 Ok(StreamProcessor::create(processor, sysmem_client, DEFAULT_MIN_OUTPUT_BUFFER_SIZE))
564 }
565
566 pub fn take_output_stream(&mut self) -> Result<StreamProcessorOutputStream, Error> {
570 {
571 let read = self.inner.read();
572 let mut lock = read.output_queue.lock();
573 if let Listener::None = lock.listener {
574 lock.listener = Listener::New;
575 } else {
576 return Err(format_err!("Output stream already taken"));
577 }
578 }
579 Ok(StreamProcessorOutputStream { inner: self.inner.clone() })
580 }
581
582 fn write_bytes(&mut self, bytes: &[u8]) -> Result<usize, io::Error> {
584 let mut bytes_idx = 0;
585 while bytes.len() > bytes_idx {
586 {
587 let mut write = self.inner.write();
588 let (idx, size) = match write.input_cursor.take() {
589 None => return Ok(bytes_idx),
590 Some(x) => x,
591 };
592 let space_left = write.input_packet_size - size;
593 let left_to_write = bytes.len() - bytes_idx;
594 let buffer_vmo = write.input_buffers().get_mut(idx.0).expect("need buffer vmo");
595 if space_left as usize > left_to_write {
596 let write_buf = &bytes[bytes_idx..];
597 let write_len = write_buf.len();
598 buffer_vmo.write(write_buf, size).map_err(|s| s.into_io_error())?;
599 bytes_idx += write_len;
600 write.input_cursor = Some((idx, size + write_len as u64));
601 assert!(bytes.len() == bytes_idx);
602 return Ok(bytes_idx);
603 }
604 let end_idx = bytes_idx + space_left as usize;
605 let write_buf = &bytes[bytes_idx..end_idx];
606 let write_len = write_buf.len();
607 buffer_vmo.write(write_buf, size).map_err(|s| s.into_io_error())?;
608 bytes_idx += write_len;
609 assert_eq!(size + write_len as u64, write.input_packet_size);
611 write.input_cursor = Some((idx, write.input_packet_size));
612 }
613 self.send_packet()?;
614 }
615 Ok(bytes_idx)
616 }
617
618 pub fn send_packet(&mut self) -> Result<(), io::Error> {
622 let mut write = self.inner.write();
623 if write.input_cursor.is_none() {
624 return Ok(());
626 }
627 let (idx, size) = write.input_cursor.take().expect("input cursor is none");
628 if size == 0 {
629 write.input_cursor = Some((idx, size));
631 return Ok(());
632 }
633 let packet = Packet {
634 header: Some(PacketHeader {
635 buffer_lifetime_ordinal: Some(1),
636 packet_index: Some(idx.0),
637 ..Default::default()
638 }),
639 buffer_index: Some(idx.0),
640 stream_lifetime_ordinal: Some(1),
641 start_offset: Some(0),
642 valid_length_bytes: Some(size as u32),
643 start_access_unit: Some(true),
644 known_end_access_unit: Some(true),
645 ..Default::default()
646 };
647 write.processor.queue_input_packet(&packet).map_err(fidl_error_to_io_error)?;
648 write.setup_input_cursor();
650 Ok(())
651 }
652
653 fn poll_writable(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
657 let mut write = self.inner.write();
658 write.input_waker = None;
661 if write.input_cursor.is_some() {
662 return Poll::Ready(Ok(()));
663 }
664 write.input_waker = Some(cx.waker().clone());
665 if let Err(e) = write.poll_events() {
670 return Poll::Ready(Err(io::Error::other(e)));
671 }
672 Poll::Pending
673 }
674
675 pub fn close(&mut self) -> Result<(), io::Error> {
676 self.send_packet()?;
677
678 let mut write = self.inner.write();
679
680 write.processor.queue_input_end_of_stream(1).map_err(fidl_error_to_io_error)?;
681 write.input_cursor = None;
684 write.wake_input();
685 write.wake_output();
686 Ok(())
687 }
688}
689
690impl AsyncWrite for StreamProcessor {
691 fn poll_write(
692 mut self: Pin<&mut Self>,
693 cx: &mut Context<'_>,
694 buf: &[u8],
695 ) -> Poll<io::Result<usize>> {
696 ready!(self.poll_writable(cx))?;
697 match self.write_bytes(buf) {
698 Ok(written) => Poll::Ready(Ok(written)),
699 Err(e) => Poll::Ready(Err(e.into())),
700 }
701 }
702
703 fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
704 Poll::Ready(self.send_packet())
705 }
706
707 fn poll_close(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
708 Poll::Ready(self.send_packet())
709 }
710}
711
712impl Stream for StreamProcessorOutputStream {
713 type Item = Result<Vec<u8>, Error>;
714
715 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
716 let mut write = self.inner.write();
717 let packet = {
719 let mut queue = write.output_queue.lock();
720 match queue.poll_next_unpin(cx) {
721 Poll::Ready(Some(packet)) => Some(Some(packet)),
722 Poll::Ready(None) => Some(None),
723 Poll::Pending => {
724 None
727 }
728 }
729 };
730 if let Err(e) = write.poll_events() {
733 return Poll::Ready(Some(Err(e.into())));
734 }
735 match packet {
736 Some(Some(packet)) => Poll::Ready(Some(write.read_output_packet(packet))),
737 Some(None) => Poll::Ready(None),
738 None => Poll::Pending,
739 }
740 }
741}
742
743impl FusedStream for StreamProcessorOutputStream {
744 fn is_terminated(&self) -> bool {
745 self.inner.read().output_queue.lock().ended
746 }
747}
748
749#[cfg(test)]
750mod tests {
751 use super::*;
752
753 use async_test_helpers::run_while;
754 use byteorder::{ByteOrder, NativeEndian};
755 use fixture::fixture;
756 use fuchsia_async as fasync;
757 use futures::FutureExt;
758 use futures::io::AsyncWriteExt;
759 use futures_test::task::new_count_waker;
760 use sha2::{Digest as _, Sha256};
761 use std::fs::File;
762 use std::io::{Read, Write};
763 use std::pin::pin;
764
765 use stream_processor_test::ExpectedDigest;
766
767 const PCM_SAMPLE_SIZE: usize = 2;
768
769 #[derive(Clone, Debug)]
770 pub struct PcmAudio {
771 pcm_format: PcmFormat,
772 buffer: Vec<u8>,
773 }
774
775 impl PcmAudio {
776 pub fn create_saw_wave(pcm_format: PcmFormat, frame_count: usize) -> Self {
777 const FREQUENCY: f32 = 20.0;
778 const AMPLITUDE: f32 = 0.2;
779
780 let pcm_frame_size = PCM_SAMPLE_SIZE * pcm_format.channel_map.len();
781 let samples_per_frame = pcm_format.channel_map.len();
782 let sample_count = frame_count * samples_per_frame;
783
784 let mut buffer = vec![0; frame_count * pcm_frame_size];
785
786 for i in 0..sample_count {
787 let frame = (i / samples_per_frame) as f32;
788 let value =
789 ((frame * FREQUENCY / (pcm_format.frames_per_second as f32)) % 1.0) * AMPLITUDE;
790 let sample = (value * i16::MAX as f32) as i16;
791
792 let mut sample_bytes = [0; std::mem::size_of::<i16>()];
793 NativeEndian::write_i16(&mut sample_bytes, sample);
794
795 let offset = i * PCM_SAMPLE_SIZE;
796 buffer[offset] = sample_bytes[0];
797 buffer[offset + 1] = sample_bytes[1];
798 }
799
800 Self { pcm_format, buffer }
801 }
802
803 pub fn frame_size(&self) -> usize {
804 self.pcm_format.channel_map.len() * PCM_SAMPLE_SIZE
805 }
806 }
807
808 pub struct BytesValidator {
811 pub output_file: Option<&'static str>,
812 pub expected_digest: ExpectedDigest,
813 }
814
815 impl BytesValidator {
816 fn write_and_hash(&self, mut file: impl Write, bytes: &[u8]) -> Result<(), Error> {
817 let mut hasher = Sha256::default();
818
819 file.write_all(&bytes)?;
820 hasher.update(&bytes);
821
822 let digest: [u8; 32] = hasher.finalize().into();
823 if self.expected_digest.bytes != digest {
824 return Err(format_err!(
825 "Expected {}; got {}",
826 self.expected_digest,
827 hex::encode(digest)
828 ))
829 .into();
830 }
831
832 Ok(())
833 }
834
835 fn output_file(&self) -> Result<impl Write, Error> {
836 Ok(if let Some(file) = self.output_file {
837 Box::new(std::fs::File::create(file)?) as Box<dyn Write>
838 } else {
839 Box::new(std::io::sink()) as Box<dyn Write>
840 })
841 }
842
843 fn validate(&self, bytes: &[u8]) -> Result<(), Error> {
844 self.write_and_hash(self.output_file()?, &bytes)
845 }
846 }
847
848 #[fuchsia::test]
849 fn encode_sbc() {
850 let mut exec = fasync::TestExecutor::new();
851
852 let pcm_format = PcmFormat {
853 pcm_mode: AudioPcmMode::Linear,
854 bits_per_sample: 16,
855 frames_per_second: 44100,
856 channel_map: vec![AudioChannelId::Cf],
857 };
858
859 let sub_bands = SbcSubBands::SubBands4;
860 let block_count = SbcBlockCount::BlockCount8;
861
862 let input_frames = 3000;
863
864 let pcm_audio = PcmAudio::create_saw_wave(pcm_format.clone(), input_frames);
865
866 let sbc_encoder_settings = EncoderSettings::Sbc(SbcEncoderSettings {
867 sub_bands,
868 block_count,
869 allocation: SbcAllocation::AllocLoudness,
870 channel_mode: SbcChannelMode::Mono,
871 bit_pool: 59, });
873
874 let input_domain = DomainFormat::Audio(AudioFormat::Uncompressed(
875 AudioUncompressedFormat::Pcm(pcm_format),
876 ));
877
878 let mut encoder = StreamProcessor::create_encoder(input_domain, sbc_encoder_settings)
879 .expect("to create Encoder");
880
881 let frames_per_packet: usize = 8; let packet_size = pcm_audio.frame_size() * frames_per_packet;
883 let mut packets = pcm_audio.buffer.as_slice().chunks(packet_size);
884 let first_packet = packets.next().unwrap();
885
886 let written =
889 exec.run_singlethreaded(&mut encoder.write(first_packet)).expect("successful write");
890 assert_eq!(written, first_packet.len());
891
892 let mut encoded_stream = encoder.take_output_stream().expect("Stream should be taken");
893
894 assert!(encoder.take_output_stream().is_err());
896
897 let encoded_fut = pin!(encoded_stream.next());
900
901 let (waker, encoder_fut_wake_count) = new_count_waker();
902 let mut counting_ctx = Context::from_waker(&waker);
903
904 assert!(encoded_fut.poll(&mut counting_ctx).is_pending());
905
906 let mut frames_sent = first_packet.len() / pcm_audio.frame_size();
907
908 for packet in packets {
909 let mut written_fut = encoder.write(&packet);
910
911 let written_bytes =
912 exec.run_singlethreaded(&mut written_fut).expect("to write to encoder");
913
914 assert_eq!(packet.len(), written_bytes);
915 frames_sent += packet.len() / pcm_audio.frame_size();
916 }
917
918 encoder.close().expect("stream should always be closable");
919
920 assert_eq!(input_frames, frames_sent);
921
922 let woke_count = encoder_fut_wake_count.get();
925 while encoder_fut_wake_count.get() == woke_count {
926 let _ = exec.run_until_stalled(&mut futures::future::pending::<()>());
927 }
928 assert_eq!(encoder_fut_wake_count.get(), woke_count + 1);
929
930 let mut encoded = Vec::new();
932
933 loop {
934 let mut encoded_fut = encoded_stream.next();
935
936 match exec.run_singlethreaded(&mut encoded_fut) {
937 Some(Ok(enc_data)) => {
938 assert!(!enc_data.is_empty());
939 encoded.extend_from_slice(&enc_data);
940 }
941 Some(Err(e)) => {
942 panic!("Unexpected error when polling encoded data: {}", e);
943 }
944 None => {
945 break;
946 }
947 }
948 }
949
950 let expected_digest = ExpectedDigest::new(
952 "Sbc: 44.1kHz/Loudness/Mono/bitpool 56/blocks 8/subbands 4",
953 "5c65a88bda3f132538966d87df34aa8675f85c9892b7f9f5571f76f3c7813562",
954 );
955 let hash_validator = BytesValidator { output_file: None, expected_digest };
956
957 assert_eq!(6110, encoded.len(), "Encoded size should be equal");
958
959 let validated = hash_validator.validate(encoded.as_slice());
960 assert!(validated.is_ok(), "Failed hash: {:?}", validated);
961 }
962
963 fn fix_sbc_test_file<F>(_name: &str, test: F)
964 where
965 F: FnOnce(Vec<u8>) -> (),
966 {
967 const SBC_TEST_FILE: &str = "/pkg/data/s16le44100mono.sbc";
968
969 let mut sbc_data = Vec::new();
970 let _ = File::open(SBC_TEST_FILE)
971 .expect("open test file")
972 .read_to_end(&mut sbc_data)
973 .expect("read test file");
974
975 test(sbc_data)
976 }
977
978 #[fixture(fix_sbc_test_file)]
979 #[fuchsia::test]
980 fn decode_sbc(sbc_data: Vec<u8>) {
981 let mut exec = fasync::TestExecutor::new();
982
983 const SBC_FRAME_SIZE: usize = 72;
984 const INPUT_FRAMES: usize = 23;
985
986 let oob_data = Some([0x82, 0x00, 0x00, 0x00].to_vec());
988 let mut decoder =
989 StreamProcessor::create_decoder("audio/sbc", oob_data).expect("to create decoder");
990
991 let mut decoded_stream = decoder.take_output_stream().expect("Stream should be taken");
992
993 assert!(decoder.take_output_stream().is_err());
995
996 let mut frames_sent = 0;
997
998 let frames_per_packet: usize = 1; let packet_size = SBC_FRAME_SIZE * frames_per_packet;
1000
1001 for frames in sbc_data.as_slice().chunks(packet_size) {
1002 let mut written_fut = decoder.write(&frames);
1003
1004 let written_bytes =
1005 exec.run_singlethreaded(&mut written_fut).expect("to write to decoder");
1006
1007 assert_eq!(frames.len(), written_bytes);
1008 frames_sent += frames.len() / SBC_FRAME_SIZE;
1009 }
1010
1011 assert_eq!(INPUT_FRAMES, frames_sent);
1012
1013 let mut flush_fut = pin!(decoder.flush());
1014 exec.run_singlethreaded(&mut flush_fut).expect("to flush the decoder");
1015
1016 decoder.close().expect("stream should always be closable");
1017
1018 let mut decoded = Vec::new();
1020
1021 loop {
1022 let mut decoded_fut = decoded_stream.next();
1023
1024 match exec.run_singlethreaded(&mut decoded_fut) {
1025 Some(Ok(dec_data)) => {
1026 assert!(!dec_data.is_empty());
1027 decoded.extend_from_slice(&dec_data);
1028 }
1029 Some(Err(e)) => {
1030 panic!("Unexpected error when polling decoded data: {}", e);
1031 }
1032 None => {
1033 break;
1034 }
1035 }
1036 }
1037
1038 let expected_digest = ExpectedDigest::new(
1040 "Pcm: 44.1kHz/16bit/Mono",
1041 "ff2e7afea51217886d3df15b9a623b4e49c9bd9bd79c58ac01bc94c5511e08d6",
1042 );
1043 let hash_validator = BytesValidator { output_file: None, expected_digest };
1044
1045 assert_eq!(256 * INPUT_FRAMES, decoded.len(), "Decoded size should be equal");
1046
1047 let validated = hash_validator.validate(decoded.as_slice());
1048 assert!(validated.is_ok(), "Failed hash: {:?}", validated);
1049 }
1050
1051 #[fixture(fix_sbc_test_file)]
1052 #[fuchsia::test]
1053 fn decode_sbc_wakes_output_to_process_events(sbc_data: Vec<u8>) {
1054 let mut exec = fasync::TestExecutor::new();
1055 const SBC_FRAME_SIZE: usize = 72;
1056
1057 let oob_data = Some([0x82, 0x00, 0x00, 0x00].to_vec());
1059 let mut decoder =
1060 StreamProcessor::create_decoder("audio/sbc", oob_data).expect("to create decoder");
1061
1062 let mut chunks = sbc_data.as_slice().chunks(SBC_FRAME_SIZE);
1063 let next_frame = chunks.next().unwrap();
1064
1065 let written =
1068 exec.run_singlethreaded(&mut decoder.write(next_frame)).expect("successful write");
1069 assert_eq!(written, next_frame.len());
1070
1071 let mut decoded_stream = decoder.take_output_stream().expect("Stream should be taken");
1072
1073 let decoded_fut = pin!(decoded_stream.next());
1076
1077 let (waker, decoder_fut_wake_count) = new_count_waker();
1078 let mut counting_ctx = Context::from_waker(&waker);
1079
1080 assert!(decoded_fut.poll(&mut counting_ctx).is_pending());
1081
1082 let frame = chunks.next().unwrap();
1085 let mut written_fut = decoder.write(&frame);
1086 let written_bytes = exec.run_singlethreaded(&mut written_fut).expect("to write to decoder");
1087 assert_eq!(frame.len(), written_bytes);
1088
1089 let mut flush_fut = pin!(decoder.flush());
1090 exec.run_singlethreaded(&mut flush_fut).expect("to flush the decoder");
1091
1092 assert_eq!(decoder_fut_wake_count.get(), 0);
1095 while decoder_fut_wake_count.get() == 0 {
1096 let _ = exec.run_until_stalled(&mut futures::future::pending::<()>());
1097 }
1098 assert_eq!(decoder_fut_wake_count.get(), 1);
1099
1100 let mut decoded = Vec::new();
1101 let mut decoded_fut = decoded_stream.next();
1103
1104 match exec.run_singlethreaded(&mut decoded_fut) {
1105 Some(Ok(dec_data)) => {
1106 assert!(!dec_data.is_empty());
1107 decoded.extend_from_slice(&dec_data);
1108 }
1109 x => panic!("Expected decoded frame, got {:?}", x),
1110 }
1111
1112 assert_eq!(512, decoded.len(), "Decoded size should be equal to one frame");
1113 }
1114
1115 #[fixture(fix_sbc_test_file)]
1116 #[fuchsia::test]
1117 fn decode_sbc_wakes_input_to_process_events(sbc_data: Vec<u8>) {
1118 let mut exec = fasync::TestExecutor::new();
1119 const SBC_FRAME_SIZE: usize = 72;
1120
1121 let oob_data = Some([0x82, 0x00, 0x00, 0x00].to_vec());
1123 let mut decoder =
1124 StreamProcessor::create_decoder("audio/sbc", oob_data).expect("to create decoder");
1125
1126 let mut decoded_stream = decoder.take_output_stream().expect("Stream should be taken");
1127
1128 let decoded_fut = pin!(decoded_stream.next());
1129
1130 let mut chunks = sbc_data.as_slice().chunks(SBC_FRAME_SIZE).cycle();
1131 let next_frame = chunks.next().unwrap();
1132
1133 let (written_res, mut decoded_fut) =
1139 run_while(&mut exec, decoded_fut, decoder.write(next_frame));
1140 assert_eq!(written_res.expect("initial write should succeed"), next_frame.len());
1141
1142 let (waker, write_fut_wake_count) = new_count_waker();
1146 let mut counting_ctx = Context::from_waker(&waker);
1147
1148 let mut wake_count_before_stall = 0;
1149 for frame in chunks {
1150 wake_count_before_stall = write_fut_wake_count.get();
1151 let mut written_fut = decoder.write(&frame);
1152 if written_fut.poll_unpin(&mut counting_ctx).is_pending() {
1153 if write_fut_wake_count.get() != wake_count_before_stall {
1156 continue;
1157 }
1158 break;
1161 }
1162 let mut flush_fut = pin!(decoder.flush());
1164 exec.run_singlethreaded(&mut flush_fut).expect("to flush the decoder");
1165 }
1166
1167 let decoded_frame = exec.run_singlethreaded(&mut decoded_fut);
1169 assert_eq!(512, decoded_frame.unwrap().unwrap().len(), "Decoded frame size wrong");
1170
1171 let chunks = sbc_data.as_slice().chunks(SBC_FRAME_SIZE).cycle();
1173 for frame in chunks {
1174 wake_count_before_stall = write_fut_wake_count.get();
1175 let mut written_fut = decoder.write(&frame);
1176 if written_fut.poll_unpin(&mut counting_ctx).is_pending() {
1177 if write_fut_wake_count.get() != wake_count_before_stall {
1180 continue;
1181 }
1182 break;
1183 }
1184 let mut flush_fut = pin!(decoder.flush());
1186 exec.run_singlethreaded(&mut flush_fut).expect("to flush the decoder");
1187 }
1188
1189 while write_fut_wake_count.get() == wake_count_before_stall {
1194 let _ = exec.run_until_stalled(&mut futures::future::pending::<()>());
1195 }
1196
1197 }
1200}