fix: display channel info
This commit is contained in:
parent
bc39a2ad99
commit
ba53d2eeb9
@ -7,14 +7,13 @@ use std::ptr;
|
||||
use anyhow::Error;
|
||||
use ffmpeg_sys_the_third::AVPictureType::AV_PICTURE_TYPE_NONE;
|
||||
use ffmpeg_sys_the_third::{
|
||||
av_buffer_alloc, av_buffer_ref, av_frame_alloc, av_frame_copy_props, av_frame_free,
|
||||
av_hwdevice_ctx_create, av_hwdevice_get_type_name, av_hwframe_transfer_data,
|
||||
avcodec_alloc_context3, avcodec_find_decoder, avcodec_free_context, avcodec_get_hw_config,
|
||||
avcodec_get_name, avcodec_open2, avcodec_parameters_to_context, avcodec_receive_frame,
|
||||
avcodec_send_packet, AVCodec, AVCodecContext, AVCodecHWConfig, AVFrame, AVHWDeviceType,
|
||||
AVMediaType, AVPacket, AVStream, AVERROR, AVERROR_EOF, AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX,
|
||||
av_buffer_ref, av_frame_alloc, av_frame_copy_props, av_frame_free, av_hwdevice_ctx_create,
|
||||
av_hwdevice_get_type_name, av_hwframe_transfer_data, avcodec_alloc_context3,
|
||||
avcodec_find_decoder, avcodec_free_context, avcodec_get_hw_config, avcodec_get_name,
|
||||
avcodec_open2, avcodec_parameters_to_context, avcodec_receive_frame, avcodec_send_packet,
|
||||
AVCodec, AVCodecContext, AVCodecHWConfig, AVFrame, AVHWDeviceType, AVPacket, AVStream, AVERROR,
|
||||
AVERROR_EOF, AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX,
|
||||
};
|
||||
use libc::memcpy;
|
||||
|
||||
pub struct DecoderCodecContext {
|
||||
pub context: *mut AVCodecContext,
|
||||
@ -204,23 +203,6 @@ impl Decoder {
|
||||
);
|
||||
|
||||
if let Some(ctx) = self.codecs.get_mut(&stream_index) {
|
||||
// subtitles don't need decoding, create a frame from the pkt data
|
||||
if (*ctx.codec).type_ == AVMediaType::AVMEDIA_TYPE_SUBTITLE {
|
||||
let frame = av_frame_alloc();
|
||||
(*frame).pts = (*pkt).pts;
|
||||
(*frame).pkt_dts = (*pkt).dts;
|
||||
(*frame).duration = (*pkt).duration;
|
||||
(*frame).buf[0] = av_buffer_alloc((*pkt).size as usize);
|
||||
(*frame).data[0] = (*(*frame).buf[0]).data;
|
||||
(*frame).linesize[0] = (*pkt).size;
|
||||
memcpy(
|
||||
(*frame).data[0] as *mut libc::c_void,
|
||||
(*pkt).data as *const libc::c_void,
|
||||
(*pkt).size as usize,
|
||||
);
|
||||
return Ok(vec![(frame, stream)]);
|
||||
}
|
||||
|
||||
let mut ret = avcodec_send_packet(ctx.context, pkt);
|
||||
if ret < 0 {
|
||||
return Err(Error::msg(format!("Failed to decode packet {}", ret)));
|
||||
|
23
src/lib.rs
23
src/lib.rs
@ -50,6 +50,29 @@ unsafe fn options_to_dict(options: HashMap<String, String>) -> Result<*mut AVDic
|
||||
Ok(dict)
|
||||
}
|
||||
|
||||
/// Format seconds value into human-readable string
|
||||
pub fn format_time(secs: f32) -> String {
|
||||
const MIN: f32 = 60.0;
|
||||
const HR: f32 = MIN * 60.0;
|
||||
|
||||
if secs >= HR {
|
||||
format!(
|
||||
"{:0>2.0}h {:0>2.0}m {:0>2.0}s",
|
||||
(secs / HR).floor(),
|
||||
((secs % HR) / MIN).floor(),
|
||||
(secs % MIN).floor()
|
||||
)
|
||||
} else if secs >= MIN {
|
||||
format!(
|
||||
"{:0>2.0}m {:0>2.0}s",
|
||||
(secs / MIN).floor(),
|
||||
(secs % MIN).floor()
|
||||
)
|
||||
} else {
|
||||
format!("{:0>2.2}s", secs)
|
||||
}
|
||||
}
|
||||
|
||||
fn list_opts(ctx: *mut libc::c_void) -> Result<Vec<String>, Error> {
|
||||
let mut opt_ptr: *const AVOption = ptr::null_mut();
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
use crate::get_ffmpeg_error_msg;
|
||||
use std::mem::transmute;
|
||||
use std::ptr;
|
||||
|
||||
|
@ -1,4 +1,7 @@
|
||||
use ffmpeg_sys_the_third::{avcodec_get_name, AVMediaType, AVStream};
|
||||
use crate::format_time;
|
||||
use ffmpeg_sys_the_third::{
|
||||
av_get_pix_fmt_name, av_get_sample_fmt_name, avcodec_get_name, AVMediaType, AVStream,
|
||||
};
|
||||
use std::ffi::CStr;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::intrinsics::transmute;
|
||||
@ -55,7 +58,20 @@ impl DemuxerInfo {
|
||||
|
||||
impl Display for DemuxerInfo {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Demuxer Info:")?;
|
||||
let bitrate_str = if self.bitrate > 1_000_000 {
|
||||
format!("{}M", self.bitrate / 1_000_000)
|
||||
} else if self.bitrate > 1_000 {
|
||||
format!("{}k", self.bitrate / 1_000)
|
||||
} else {
|
||||
self.bitrate.to_string()
|
||||
};
|
||||
|
||||
write!(
|
||||
f,
|
||||
"Demuxer Info: duration={}, bitrate={}k",
|
||||
format_time(self.duration),
|
||||
bitrate_str
|
||||
)?;
|
||||
for c in &self.channels {
|
||||
write!(f, "\n {}", c)?;
|
||||
}
|
||||
@ -115,15 +131,44 @@ impl StreamInfoChannel {
|
||||
impl Display for StreamInfoChannel {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
let codec_name = unsafe { CStr::from_ptr(avcodec_get_name(transmute(self.codec as i32))) };
|
||||
write!(
|
||||
match self.channel_type {
|
||||
StreamChannelType::Video => write!(
|
||||
f,
|
||||
"{} #{}: codec={},size={}x{},fps={}",
|
||||
"{} #{}: codec={},size={}x{},fps={:.3},pix_fmt={}",
|
||||
self.channel_type,
|
||||
self.index,
|
||||
codec_name.to_str().unwrap(),
|
||||
self.width,
|
||||
self.height,
|
||||
self.fps
|
||||
)
|
||||
self.fps,
|
||||
unsafe {
|
||||
CStr::from_ptr(av_get_pix_fmt_name(transmute(self.format as libc::c_int)))
|
||||
}
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
),
|
||||
StreamChannelType::Audio => write!(
|
||||
f,
|
||||
"{} #{}: codec={},format={},sample_rate={}",
|
||||
self.channel_type,
|
||||
self.index,
|
||||
codec_name.to_str().unwrap(),
|
||||
unsafe {
|
||||
CStr::from_ptr(av_get_sample_fmt_name(transmute(
|
||||
self.format as libc::c_int,
|
||||
)))
|
||||
}
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
self.sample_rate,
|
||||
),
|
||||
StreamChannelType::Subtitle => write!(
|
||||
f,
|
||||
"{} #{}: codec={}",
|
||||
self.channel_type,
|
||||
self.index,
|
||||
codec_name.to_str().unwrap()
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user