refactor: Remove dead FFmpeg code from pmoparadise
Remove unused FFmpeg-based progressive streaming implementation that was never completed and is not used anywhere in the codebase. Changes: - Delete src/ffmpeg_streaming.rs (173 lines of unfinished code with TODOs) - Remove ffmpeg module import from lib.rs - Remove ffmpeg feature from Cargo.toml - Remove ffmpeg-next dependency from Cargo.toml The current implementation uses claxon (StreamingPCMDecoder) and symphonia (decode_block_audio) for FLAC decoding, which are fully functional. Verified: cargo check passes successfully after removal.
This commit is contained in:
@@ -1,172 +0,0 @@
|
||||
//! FFmpeg-based progressive streaming decoder/encoder
|
||||
//!
|
||||
//! This module provides progressive audio streaming using FFmpeg,
|
||||
//! allowing for much lower latency than the claxon/flacenc approach.
|
||||
//!
|
||||
//! Key advantages:
|
||||
//! - Start streaming immediately (< 1 second latency)
|
||||
//! - Progressive decoding and encoding in a pipeline
|
||||
//! - Better performance (C code vs Rust)
|
||||
//! - Support for multiple output formats
|
||||
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use bytes::Bytes;
|
||||
use ffmpeg_next as ffmpeg;
|
||||
use std::io::{Read, Write};
|
||||
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
|
||||
use tokio::task;
|
||||
use tracing::{debug, error, trace};
|
||||
|
||||
/// Initialize FFmpeg (must be called once at startup)
|
||||
pub fn init() -> Result<()> {
|
||||
ffmpeg::init().context("Failed to initialize FFmpeg")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// PCM chunk with decoded audio data
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PCMChunk {
|
||||
pub samples: Vec<i16>, // Interleaved 16-bit samples
|
||||
pub sample_rate: u32,
|
||||
pub channels: u32,
|
||||
pub position_ms: u64,
|
||||
}
|
||||
|
||||
/// Progressive decoder that decodes FLAC data as it arrives
|
||||
pub struct ProgressiveDecoder {
|
||||
input_rx: Receiver<Result<Bytes, String>>,
|
||||
buffer: Vec<u8>,
|
||||
decoder_ctx: Option<ffmpeg::codec::context::Context>,
|
||||
sample_rate: u32,
|
||||
channels: u32,
|
||||
total_samples_decoded: u64,
|
||||
}
|
||||
|
||||
impl ProgressiveDecoder {
|
||||
/// Create a new progressive decoder from a byte stream
|
||||
pub fn new(mut stream: impl Read + Send + 'static) -> Result<Self> {
|
||||
let (tx, rx) = sync_channel(64);
|
||||
|
||||
// Spawn a thread to read from the stream and feed chunks
|
||||
std::thread::spawn(move || {
|
||||
let mut buffer = vec![0u8; 8192];
|
||||
loop {
|
||||
match stream.read(&mut buffer) {
|
||||
Ok(0) => break, // EOF
|
||||
Ok(n) => {
|
||||
let chunk = Bytes::copy_from_slice(&buffer[..n]);
|
||||
if tx.send(Ok(chunk)).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
let _ = tx.send(Err(e.to_string()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Ok(Self {
|
||||
input_rx: rx,
|
||||
buffer: Vec::with_capacity(65536),
|
||||
decoder_ctx: None,
|
||||
sample_rate: 0,
|
||||
channels: 0,
|
||||
total_samples_decoded: 0,
|
||||
})
|
||||
}
|
||||
|
||||
/// Decode the next chunk of PCM data
|
||||
pub fn decode_chunk(&mut self) -> Result<Option<PCMChunk>> {
|
||||
// Receive more data from the stream
|
||||
while self.buffer.len() < 4096 {
|
||||
match self.input_rx.try_recv() {
|
||||
Ok(Ok(bytes)) => {
|
||||
self.buffer.extend_from_slice(&bytes);
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
return Err(anyhow!("Stream error: {}", e));
|
||||
}
|
||||
Err(std::sync::mpsc::TryRecvError::Empty) => {
|
||||
// No more data available right now
|
||||
break;
|
||||
}
|
||||
Err(std::sync::mpsc::TryRecvError::Disconnected) => {
|
||||
// Stream ended
|
||||
if self.buffer.is_empty() {
|
||||
return Ok(None);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if self.buffer.is_empty() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
// Initialize decoder on first call
|
||||
if self.decoder_ctx.is_none() {
|
||||
self.init_decoder()?;
|
||||
}
|
||||
|
||||
// Decode a frame
|
||||
// TODO: Implement actual FFmpeg decoding
|
||||
// For now, return a placeholder
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn init_decoder(&mut self) -> Result<()> {
|
||||
// TODO: Initialize FFmpeg decoder from buffer
|
||||
// Parse FLAC header, create decoder context
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Progressive encoder that encodes PCM to FLAC as data arrives
|
||||
pub struct ProgressiveEncoder {
|
||||
output_tx: SyncSender<Bytes>,
|
||||
encoder_ctx: Option<ffmpeg::codec::context::Context>,
|
||||
sample_rate: u32,
|
||||
channels: u32,
|
||||
}
|
||||
|
||||
impl ProgressiveEncoder {
|
||||
/// Create a new progressive encoder
|
||||
pub fn new(sample_rate: u32, channels: u32) -> Result<(Self, Receiver<Bytes>)> {
|
||||
let (tx, rx) = sync_channel(64);
|
||||
|
||||
let encoder = Self {
|
||||
output_tx: tx,
|
||||
encoder_ctx: None,
|
||||
sample_rate,
|
||||
channels,
|
||||
};
|
||||
|
||||
Ok((encoder, rx))
|
||||
}
|
||||
|
||||
/// Encode a chunk of PCM data
|
||||
pub fn encode_chunk(&mut self, pcm: &PCMChunk) -> Result<()> {
|
||||
// TODO: Implement FFmpeg encoding
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Flush any remaining encoded data
|
||||
pub fn flush(&mut self) -> Result<()> {
|
||||
// TODO: Flush encoder
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_ffmpeg_init() {
|
||||
assert!(init().is_ok());
|
||||
}
|
||||
}
|
||||
@@ -229,9 +229,6 @@ pub mod streaming;
|
||||
#[cfg(feature = "per-track")]
|
||||
pub mod track;
|
||||
|
||||
#[cfg(feature = "ffmpeg")]
|
||||
pub mod ffmpeg_streaming;
|
||||
|
||||
#[cfg(feature = "pmoserver")]
|
||||
pub mod pmoserver_ext;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user