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

@ -4,7 +4,7 @@ use std::mem;
use ffi::*;
use libc::{c_int, c_uint};
use ::{media, Stream, StreamMut, DictionaryRef};
use ::{media, Stream, StreamMut, Chapter, ChapterMut, DictionaryRef};
use super::destructor::{self, Destructor};
pub struct Context {
@ -69,6 +69,42 @@ impl Context {
}
}
pub fn nb_chapters(&self) -> u32 {
unsafe {
(*self.as_ptr()).nb_chapters
}
}
pub fn chapter<'a, 'b>(&'a self, index: usize) -> Option<Chapter<'b>> where 'a: 'b {
unsafe {
if index >= (*self.as_ptr()).nb_chapters as usize {
None
}
else {
Some(Chapter::wrap(self, index))
}
}
}
pub fn chapter_mut<'a, 'b>(&'a mut self, index: usize) -> Option<ChapterMut<'b>> where 'a: 'b {
unsafe {
if index >= (*self.as_ptr()).nb_chapters as usize {
None
}
else {
Some(ChapterMut::wrap(self, index))
}
}
}
pub fn chapters(&self) -> ChapterIter {
ChapterIter::new(self)
}
pub fn chapters_mut(&mut self) -> ChapterIterMut {
ChapterIterMut::new(self)
}
pub fn metadata(&self) -> DictionaryRef {
unsafe {
DictionaryRef::wrap((*self.as_ptr()).metadata)
@ -213,3 +249,77 @@ impl<'a> Iterator for StreamIterMut<'a> {
}
impl<'a> ExactSizeIterator for StreamIterMut<'a> { }
pub struct ChapterIter<'a> {
context: &'a Context,
current: c_uint,
}
impl<'a> ChapterIter<'a> {
pub fn new<'s, 'c: 's>(context: &'c Context) -> ChapterIter<'s> {
ChapterIter { context: context, current: 0 }
}
}
impl<'a> Iterator for ChapterIter<'a> {
type Item = Chapter<'a>;
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe {
if self.current >= (*self.context.as_ptr()).nb_chapters {
return None;
}
self.current += 1;
Some(Chapter::wrap(self.context, (self.current - 1) as usize))
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
unsafe {
let length = (*self.context.as_ptr()).nb_chapters as usize;
(length - self.current as usize, Some(length - self.current as usize))
}
}
}
impl<'a> ExactSizeIterator for ChapterIter<'a> { }
pub struct ChapterIterMut<'a> {
context: &'a mut Context,
current: c_uint,
}
impl<'a> ChapterIterMut<'a> {
pub fn new<'s, 'c: 's>(context: &'c mut Context) -> ChapterIterMut<'s> {
ChapterIterMut { context: context, current: 0 }
}
}
impl<'a> Iterator for ChapterIterMut<'a> {
type Item = ChapterMut<'a>;
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
unsafe {
if self.current >= (*self.context.as_ptr()).nb_chapters {
return None
}
self.current += 1;
Some(ChapterMut::wrap(mem::transmute_copy(&self.context), (self.current - 1) as usize))
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
unsafe {
let length = (*self.context.as_ptr()).nb_chapters as usize;
(length - self.current as usize, Some(length - self.current as usize))
}
}
}
impl<'a> ExactSizeIterator for ChapterIterMut<'a> { }