Clarified reciprocal framerate / timebase usage
This commit is contained in:
parent
3c10219a47
commit
f37c92e58d
|
@ -71,9 +71,9 @@ func NewDecoder(r io.Reader, settings map[string]any) (d *Decoder, err error) {
|
|||
PixelAspectRatio: fP.PixelAspectRatio,
|
||||
ColorSpace: fP.ColorSpace,
|
||||
FrameRate: utilities.Ratio{
|
||||
Numerator: int(d.h.TimebaseDenominator),
|
||||
Denominator: int(d.h.TimebaseNumerator),
|
||||
},
|
||||
Numerator: int(d.h.TimebaseNumerator),
|
||||
Denominator: int(d.h.TimebaseDenominator),
|
||||
}.Reciprocal(),
|
||||
FullColorRange: fP.FullColorRange,
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ type Encoder struct {
|
|||
cfg C.aom_codec_enc_cfg_t
|
||||
codec C.aom_codec_ctx_t
|
||||
raw *C.aom_image_t
|
||||
frames uint32
|
||||
}
|
||||
|
||||
var libaomVersion = "libaom-av1 " + C.GoString(C.aom_codec_version_str())
|
||||
|
@ -116,8 +117,23 @@ func NewEncoder(w io.Writer, properties frame.StreamProperties, settings map[str
|
|||
|
||||
e.cfg.g_w = C.uint(properties.Width)
|
||||
e.cfg.g_h = C.uint(properties.Height)
|
||||
e.cfg.g_timebase.num = C.int(properties.FrameRate.Denominator)
|
||||
e.cfg.g_timebase.den = C.int(properties.FrameRate.Numerator)
|
||||
|
||||
/*!\brief Stream timebase units
|
||||
*
|
||||
* Indicates the smallest interval of time, in seconds, used by the stream.
|
||||
* For fixed frame rate material, or variable frame rate material where
|
||||
* frames are timed at a multiple of a given clock (ex: video capture),
|
||||
* the \ref RECOMMENDED method is to set the timebase to the reciprocal
|
||||
* of the frame rate (ex: 1001/30000 for 29.970 Hz NTSC). This allows the
|
||||
* pts to correspond to the frame number, which can be handy. For
|
||||
* re-encoding video from containers with absolute time timestamps, the
|
||||
* \ref RECOMMENDED method is to set the timebase to that of the parent
|
||||
* container or multimedia framework (ex: 1/1000 for ms, as in FLV).
|
||||
*/
|
||||
reciprocalFrameRate := properties.FrameRate.Reciprocal()
|
||||
|
||||
e.cfg.g_timebase.num = C.int(reciprocalFrameRate.Numerator)
|
||||
e.cfg.g_timebase.den = C.int(reciprocalFrameRate.Denominator)
|
||||
|
||||
e.cfg.g_threads = C.uint(getSettingInt(settings, "threads", int(e.cfg.g_threads)))
|
||||
e.cfg.g_lag_in_frames = C.uint(getSettingInt(settings, "lag-in-frames", int(e.cfg.g_lag_in_frames)))
|
||||
|
@ -193,7 +209,7 @@ func NewEncoder(w io.Writer, properties frame.StreamProperties, settings map[str
|
|||
}
|
||||
|
||||
var err error
|
||||
if e.w, err = obuwriter.NewWriter(w, properties.Width, properties.Height, 0x31305641, properties.FrameRate); err != nil {
|
||||
if e.w, err = obuwriter.NewWriter(w, properties.Width, properties.Height, 0x31305641, reciprocalFrameRate); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -233,6 +249,8 @@ func (e *Encoder) Encode(f frame.Frame) error {
|
|||
return err
|
||||
}
|
||||
|
||||
e.frames++
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -284,7 +302,7 @@ func (e *Encoder) Flush() error {
|
|||
}
|
||||
}
|
||||
|
||||
_ = e.w.WriteLength()
|
||||
_ = e.w.WriteLength(e.frames)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -8,11 +8,10 @@ import (
|
|||
)
|
||||
|
||||
type Writer struct {
|
||||
w io.Writer
|
||||
frames uint32
|
||||
w io.Writer
|
||||
}
|
||||
|
||||
func NewWriter(w io.Writer, width, height int, fourCC uint32, frameRate utilities.Ratio) (*Writer, error) {
|
||||
func NewWriter(w io.Writer, width, height int, fourCC uint32, timeBase utilities.Ratio) (*Writer, error) {
|
||||
if err := binary.Write(w, binary.LittleEndian, struct {
|
||||
Magic [4]byte
|
||||
Version uint16
|
||||
|
@ -31,8 +30,8 @@ func NewWriter(w io.Writer, width, height int, fourCC uint32, frameRate utilitie
|
|||
FourCC: fourCC,
|
||||
Width: uint16(width),
|
||||
Height: uint16(height),
|
||||
Denominator: uint32(frameRate.Numerator),
|
||||
Numerator: uint32(frameRate.Denominator),
|
||||
Denominator: uint32(timeBase.Denominator),
|
||||
Numerator: uint32(timeBase.Numerator),
|
||||
Length: 0,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
|
@ -52,20 +51,18 @@ func (w *Writer) WriteFrameBytes(pts uint64, data []byte) error {
|
|||
return err
|
||||
}
|
||||
|
||||
w.frames++
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteLength writes the Length field for number of frames, if writer was set to io.WriteSeeker
|
||||
func (w *Writer) WriteLength() error {
|
||||
func (w *Writer) WriteLength(frames uint32) error {
|
||||
if seeker, ok := w.w.(io.WriteSeeker); ok {
|
||||
if currentIndex, err := seeker.Seek(0, io.SeekCurrent); err != nil {
|
||||
return err
|
||||
} else {
|
||||
if _, err = seeker.Seek(4+2+2+4+2+2+4+4, io.SeekStart); err != nil {
|
||||
return err
|
||||
} else if err = binary.Write(w.w, binary.LittleEndian, w.frames); err != nil {
|
||||
} else if err = binary.Write(w.w, binary.LittleEndian, frames); err != nil {
|
||||
return err
|
||||
} else if _, err = seeker.Seek(currentIndex, io.SeekStart); err != nil {
|
||||
return err
|
||||
|
|
|
@ -14,3 +14,8 @@ func (r Ratio) Float64() float64 {
|
|||
func (r Ratio) String() string {
|
||||
return fmt.Sprintf("%d:%d", r.Numerator, r.Denominator)
|
||||
}
|
||||
|
||||
// Reciprocal get the reciprocal, for example, to convert frame rate into time base
|
||||
func (r Ratio) Reciprocal() Ratio {
|
||||
return Ratio{Numerator: r.Denominator, Denominator: r.Numerator}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue