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:
26
Cargo.lock
generated
26
Cargo.lock
generated
@@ -1095,31 +1095,6 @@ dependencies = [
|
|||||||
"simd-adler32",
|
"simd-adler32",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ffmpeg-next"
|
|
||||||
version = "8.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d658424d233cbd993a972dd73a66ca733acd12a494c68995c9ac32ae1fe65b40"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 2.10.0",
|
|
||||||
"ffmpeg-sys-next",
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ffmpeg-sys-next"
|
|
||||||
version = "8.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9bca20aa4ee774fe384c2490096c122b0b23cf524a9910add0686691003d797b"
|
|
||||||
dependencies = [
|
|
||||||
"bindgen",
|
|
||||||
"cc",
|
|
||||||
"libc",
|
|
||||||
"num_cpus",
|
|
||||||
"pkg-config",
|
|
||||||
"vcpkg",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "find-msvc-tools"
|
name = "find-msvc-tools"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
@@ -2905,7 +2880,6 @@ dependencies = [
|
|||||||
"bytes",
|
"bytes",
|
||||||
"chrono",
|
"chrono",
|
||||||
"claxon",
|
"claxon",
|
||||||
"ffmpeg-next",
|
|
||||||
"flacenc",
|
"flacenc",
|
||||||
"futures",
|
"futures",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
|||||||
@@ -51,9 +51,6 @@ symphonia = { version = "0.5", features = ["all"] }
|
|||||||
# Audio decoding - claxon for FLAC streaming
|
# Audio decoding - claxon for FLAC streaming
|
||||||
claxon = "0.4"
|
claxon = "0.4"
|
||||||
|
|
||||||
# FFmpeg for progressive streaming (decoding + encoding) - optional
|
|
||||||
ffmpeg-next = { version = "8.0", optional = true }
|
|
||||||
|
|
||||||
# Per-track feature dependencies
|
# Per-track feature dependencies
|
||||||
hound = { version = "3.5", optional = true }
|
hound = { version = "3.5", optional = true }
|
||||||
tempfile = { version = "3.8", optional = true }
|
tempfile = { version = "3.8", optional = true }
|
||||||
@@ -94,8 +91,6 @@ server = ["pmosource/server", "pmoconfig"]
|
|||||||
pmoconfig = ["dep:pmoconfig"]
|
pmoconfig = ["dep:pmoconfig"]
|
||||||
# Feature cache (deprecated - toujours actif maintenant)
|
# Feature cache (deprecated - toujours actif maintenant)
|
||||||
cache = []
|
cache = []
|
||||||
# Active le streaming progressif avec FFmpeg (latence réduite)
|
|
||||||
ffmpeg = ["dep:ffmpeg-next"]
|
|
||||||
# Active le support pmoaudio node (RadioParadiseStreamSource)
|
# Active le support pmoaudio node (RadioParadiseStreamSource)
|
||||||
pmoaudio = ["dep:pmoaudio", "dep:pmoflac", "dep:pmometadata", "dep:futures-util"]
|
pmoaudio = ["dep:pmoaudio", "dep:pmoflac", "dep:pmometadata", "dep:futures-util"]
|
||||||
|
|
||||||
|
|||||||
@@ -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")]
|
#[cfg(feature = "per-track")]
|
||||||
pub mod track;
|
pub mod track;
|
||||||
|
|
||||||
#[cfg(feature = "ffmpeg")]
|
|
||||||
pub mod ffmpeg_streaming;
|
|
||||||
|
|
||||||
#[cfg(feature = "pmoserver")]
|
#[cfg(feature = "pmoserver")]
|
||||||
pub mod pmoserver_ext;
|
pub mod pmoserver_ext;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user