Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions av/container/input.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,11 @@ from av.stream cimport Stream

cdef class InputContainer(Container):
cdef void flush_buffers(self)


cdef class Program:
cdef InputContainer container
cdef readonly int index
cdef lib.AVProgram *_ptr(self)

cdef Program wrap_program(InputContainer container, int index)
118 changes: 117 additions & 1 deletion av/container/input.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import cython
from cython.cimports.av.codec.context import CodecContext, wrap_codec_context
from cython.cimports.av.container.program import wrap_program
from cython.cimports.av.container.streams import StreamContainer
from cython.cimports.av.dictionary import Dictionary
from cython.cimports.av.packet import Packet
Expand All @@ -9,6 +8,10 @@
from cython.cimports.libc.stdint import int64_t, uint8_t
from cython.cimports.libc.stdlib import free, malloc

from av.stream import Discard

_cinit_bypass_sentinel = cython.declare(object, object())


@cython.cfunc
def close_input(self: InputContainer) -> cython.void:
Expand Down Expand Up @@ -388,3 +391,116 @@ def flush_buffers(self) -> cython.void:
codec_context = stream.cctx
if codec_context:
codec_context.flush_buffers()


@cython.cfunc
def wrap_program(container: InputContainer, index: cython.int) -> Program:
obj: Program = Program(_cinit_bypass_sentinel)
obj.container = container
obj.index = index
return obj


@cython.final
@cython.cclass
class Program:
"""A program in a container: a group of streams that play together.

MPEG-TS carries several programs (TV channels, in broadcast) in one stream.
Other formats, such as HLS, use programs for their variants.

Wraps :ffmpeg:`AVProgram`. Get one from :attr:`.InputContainer.programs`.
"""

def __cinit__(self, sentinel):
if sentinel is not _cinit_bypass_sentinel:
raise RuntimeError("cannot manually instantiate Program")

@cython.cfunc
def _ptr(self) -> cython.pointer[lib.AVProgram]:
self.container._assert_open()
return self.container.ptr.programs[self.index]

def __repr__(self):
if self.container.ptr == cython.NULL:
return f"<av.Program #{self.index} (container closed) at 0x{id(self):x}>"
return (
f"<av.Program #{self.index} id={self.id}, "
f"{len(self.streams)} streams at 0x{id(self):x}>"
)

@property
def id(self):
"""The format-specific ID of this program. In MPEG-TS, this is the
program number (service ID).

:type: int
"""
return self._ptr().id

@property
def program_num(self):
"""The MPEG-TS program number, or 0 for other formats.

:type: int
"""
return self._ptr().program_num

@property
def pmt_pid(self):
"""The PID of this program's Program Map Table in MPEG-TS.

:type: int
"""
return self._ptr().pmt_pid

@property
def pcr_pid(self):
"""The PID carrying this program's clock reference in MPEG-TS.

:type: int
"""
return self._ptr().pcr_pid

@property
def metadata(self):
"""Metadata for this program, such as ``service_name`` and
``service_provider`` in MPEG-TS.

:type: dict[str, str]
"""
return avdict_to_dict(self._ptr().metadata)

@property
def streams(self):
"""The streams that belong to this program.

A stream can belong to more than one program.

:type: tuple[Stream, ...]
"""
ptr: cython.pointer[lib.AVProgram] = self._ptr()
by_index = {stream.index: stream for stream in self.container.streams}
result = []
i: cython.uint
for i in range(ptr.nb_stream_indexes):
stream = by_index.get(ptr.stream_index[i])
if stream is not None:
result.append(stream)
return tuple(result)

@property
def discard(self):
"""Controls whether the demuxer reads this program's packets.

Set to :attr:`.Discard.all` to skip a program entirely. In MPEG-TS, a
stream's packets are only dropped once every program it belongs to is
discarded.

:type: Discard
"""
return Discard(self._ptr().discard)

@discard.setter
def discard(self, value):
self._ptr().discard = Discard(value).value
24 changes: 22 additions & 2 deletions av/container/input.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,36 @@ from typing import Literal, final, overload
from av.audio.frame import AudioFrame
from av.audio.stream import AudioStream
from av.packet import Packet
from av.stream import AttachmentStream, DataStream, Stream
from av.stream import AttachmentStream, DataStream, Discard, Stream
from av.subtitles.stream import SubtitleStream
from av.subtitles.subtitle import SubtitleSet
from av.video.frame import VideoFrame
from av.video.stream import VideoStream

from .core import Container
from .program import Program
from .streams import _Indices, _StreamSelector

@final
class Program:
@property
def index(self) -> int: ...
@property
def id(self) -> int: ...
@property
def program_num(self) -> int: ...
@property
def pmt_pid(self) -> int: ...
@property
def pcr_pid(self) -> int: ...
@property
def metadata(self) -> dict[str, str]: ...
@property
def streams(self) -> tuple[Stream, ...]: ...
@property
def discard(self) -> Discard: ...
@discard.setter
def discard(self, value: Discard | int) -> None: ...

@final
class InputContainer(Container):
start_time: int | None
Expand Down
11 changes: 0 additions & 11 deletions av/container/program.pxd

This file was deleted.

121 changes: 0 additions & 121 deletions av/container/program.py

This file was deleted.

24 changes: 0 additions & 24 deletions av/container/program.pyi

This file was deleted.

6 changes: 1 addition & 5 deletions docs/api/container.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,9 @@ Input Containers
Programs
--------

.. currentmodule:: av.container.program

.. autoclass:: Program
.. autoclass:: av.container.input.Program
:members:

.. currentmodule:: av.container


Output Containers
-----------------
Expand Down
2 changes: 1 addition & 1 deletion tests/test_programs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import pytest

import av
from av.container.program import Program
from av.container.input import Program
from av.stream import Discard

from .common import fate_suite
Expand Down
Loading