format: add support for Chapters

Read chapters from an input context and add chapters to an output context.

Note: unlike avformat_new_stream, the equivalent function for chapter is private:
avpriv_new_chapter (part of libavformat/internal.h). I couldn't find any other
solution but re-implementing it in format::context::output::add_chapter.
This commit is contained in:
fengalin
2017-07-22 21:22:26 +02:00
committed by meh
parent d29deedad9
commit 28b7a82ac1
8 changed files with 381 additions and 2 deletions

View File

@ -1,9 +1,12 @@
use std::ops::{Deref, DerefMut};
use std::ptr;
use std::mem::size_of;
use std::ffi::CString;
use libc;
use ffi::*;
use ::{Error, StreamMut, Dictionary, format};
use ::{Error, StreamMut, ChapterMut, Rational, Dictionary, format};
use super::common::Context;
use super::destructor;
use codec::traits;
@ -81,6 +84,65 @@ impl Output {
}
}
pub fn add_chapter<R: Into<Rational>, S: AsRef<str>>(&mut self,
id: i32,
time_base: R,
start: i64,
end: i64,
title: S) -> Result<ChapterMut, Error>
{
// avpriv_new_chapter is private (libavformat/internal.h)
if start > end {
return Err(Error::InvalidData);
}
let mut existing = None;
for chapter in self.chapters() {
if chapter.id() == id {
existing = Some(chapter.index());
break;
}
}
let index = match existing {
Some(index) => index,
None => unsafe {
let ptr = av_mallocz(size_of::<AVChapter>()).as_mut().ok_or(Error::Bug)?;
let mut nb_chapters = (*self.as_ptr()).nb_chapters as i32;
// chapters array will be freed by `avformat_free_context`
av_dynarray_add(
&mut (*self.as_mut_ptr()).chapters as *mut _ as *mut libc::c_void,
&mut nb_chapters,
ptr
);
if nb_chapters > 0 {
(*self.as_mut_ptr()).nb_chapters = nb_chapters as u32;
let index = (*self.ctx.as_ptr()).nb_chapters - 1;
index as usize
}
else {
// failed to add the chapter
av_freep(ptr);
return Err(Error::Bug);
}
},
};
let mut chapter = self.chapter_mut(index)
.ok_or(Error::Bug)?;
chapter.set_id(id);
chapter.set_time_base(time_base);
chapter.set_start(start);
chapter.set_end(end);
chapter.set_metadata("title", title);
Ok(chapter)
}
pub fn set_metadata(&mut self, dictionary: Dictionary) {
unsafe {
(*self.as_mut_ptr()).metadata = dictionary.disown();