Skip to content

Commit

Permalink
refactor: 使用性能更好的 avRescaleQ2 来做时间基转换
Browse files Browse the repository at this point in the history
  • Loading branch information
zhaohappy committed Jan 18, 2025
1 parent d0aa7df commit f7e293a
Show file tree
Hide file tree
Showing 25 changed files with 125 additions and 110 deletions.
1 change: 1 addition & 0 deletions site/.dumi/theme/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export default function (api) {
configFile: path.resolve(__dirname, '../../tsconfig.json'),
getCustomTransformers: function(program) {
const before = transformer.before(program, {
tmpPath: path.resolve(__dirname, '../../dist/'),
projectPath: path.resolve(__dirname, '../../../'),
exclude: /__test__/,
reportError: (message) => {
Expand Down
3 changes: 0 additions & 3 deletions site/docs/demo/audio-encode-wasm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,6 @@ async function encode(set: (v: string) => void) {
if (resampler) {
resampler.resample(frame.extendedData, addressof(pcmBuffer), frame.nbSamples)
newFrame = avPCMBuffer2AVFrame(addressof(pcmBuffer), false, frame)
newFrame.pts = frame.pts
newFrame.duration = frame.duration
newFrame.timeBase = frame.timeBase
}
let ret = encoder.encode(newFrame)
if (ret < 0) {
Expand Down
3 changes: 0 additions & 3 deletions site/docs/demo/audio-encode-webcodecs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,6 @@ async function encode(set: (v: string) => void) {
if (resampler) {
resampler.resample(frame.extendedData, addressof(pcmBuffer), frame.nbSamples)
newFrame = avPCMBuffer2AVFrame(addressof(pcmBuffer), false, frame)
newFrame.pts = frame.pts
newFrame.duration = frame.duration
newFrame.timeBase = frame.timeBase
}
let ret = encoder.encode(newFrame)
if (ret < 0) {
Expand Down
4 changes: 2 additions & 2 deletions src/avcodec/wasmcodec/AudioEncoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import { Rational } from 'avutil/struct/rational'
import { mapUint8Array, memcpyFromUint8Array } from 'cheap/std/memory'
import { getBytesPerSample, sampleFormatIsPlanar, sampleSetSilence } from 'avutil/util/sample'
import { AVSampleFormat } from 'avutil/audiosamplefmt'
import { avRescaleQ } from 'avutil/util/rational'
import { avRescaleQ2 } from 'avutil/util/rational'
import support from 'common/util/support'
import isPointer from 'cheap/std/function/isPointer'
import { AVDictionary } from 'avutil/struct/avdict'
Expand Down Expand Up @@ -318,7 +318,7 @@ export default class WasmAudioEncoder {
if (this.audioFrameResizer && this.audioFrameResizer.remainFrameSize() > 0) {
const avframe = createAVFrame()
this.audioFrameResizer.flush(avframe)
avframe.pts = avRescaleQ(avframe.pts, avframe.timeBase, this.timeBase)
avframe.pts = avRescaleQ2(avframe.pts, addressof(avframe.timeBase), this.timeBase)
this.encode_(avframe)
destroyAVFrame(avframe)
}
Expand Down
4 changes: 2 additions & 2 deletions src/avcodec/wasmcodec/VideoEncoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ import * as object from 'common/util/object'
import * as dict from 'avutil/util/avdict'
import * as is from 'common/util/is'
import { avMallocz } from 'avutil/util/mem'
import { avRescaleQ } from 'avutil/util/rational'
import { avRescaleQ, avRescaleQ2 } from 'avutil/util/rational'
import { NOPTS_VALUE_BIGINT } from 'avutil/constant'

export type WasmVideoEncoderOptions = {
Expand Down Expand Up @@ -226,7 +226,7 @@ export default class WasmVideoEncoder {
}

if (frame.pts !== NOPTS_VALUE_BIGINT) {
frame.pts = avRescaleQ(frame.pts, frame.timeBase, this.timeBase)
frame.pts = avRescaleQ2(frame.pts, addressof(frame.timeBase), this.timeBase)
}
else {
frame.pts = avRescaleQ(this.inputCounter, this.framerateTimebase, this.timeBase)
Expand Down
18 changes: 12 additions & 6 deletions src/avcodec/webcodec/VideoEncoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import AVCodecParameters from 'avutil/struct/avcodecparameters'
import AVFrame, { AVFramePool, AVFrameRef } from 'avutil/struct/avframe'
import getVideoCodec from 'avutil/function/getVideoCodec'
import { getHardwarePreference } from 'avutil/function/getHardwarePreference'
import { avQ2D, avRescaleQ } from 'avutil/util/rational'
import { avQ2D, avRescaleQ, avRescaleQ2 } from 'avutil/util/rational'
import { avframe2VideoFrame } from 'avutil/function/avframe2VideoFrame'
import { createAVPacket, getAVPacketData } from 'avutil/util/avpacket'
import { BitFormat } from 'avutil/codecs/h264'
Expand Down Expand Up @@ -246,11 +246,17 @@ export default class WebVideoEncoder {
if (isPointer(frame) && frame.pts !== NOPTS_VALUE_BIGINT
|| !isPointer(frame) && frame.timestamp >= 0
) {
pts = avRescaleQ(
isPointer(frame) ? frame.pts : static_cast<int64>(frame.timestamp as uint32),
isPointer(frame) ? frame.timeBase : AV_TIME_BASE_Q,
this.timeBase
)
pts = isPointer(frame)
? avRescaleQ2(
frame.pts,
addressof(frame.timeBase),
this.timeBase
)
: avRescaleQ(
static_cast<int64>(frame.timestamp as uint32),
AV_TIME_BASE_Q,
this.timeBase
)
}

if (isPointer(frame)) {
Expand Down
26 changes: 15 additions & 11 deletions src/avfilter/RangeFilterNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { AV_TIME_BASE_Q } from 'avutil/constant'
import AVFilterNode, { AVFilterNodeOptions } from './AVFilterNode'
import AVFrame, { AVFrameRef } from 'avutil/struct/avframe'
import { createAVFrame, destroyAVFrame, refAVFrame } from 'avutil/util/avframe'
import { avRescaleQ } from 'avutil/util/rational'
import { avRescaleQ2 } from 'avutil/util/rational'
import isPointer from 'cheap/std/function/isPointer'
import { IOError } from 'common/io/error'
import * as is from 'common/util/is'
Expand Down Expand Up @@ -41,11 +41,13 @@ export default class RangeFilterNode extends AVFilterNode {
return
}

let pts = avRescaleQ(
isPointer(avframe) ? avframe.pts : static_cast<int64>((avframe as VideoFrame).timestamp as uint32),
isPointer(avframe) ? avframe.timeBase : AV_TIME_BASE_Q,
AV_TIME_BASE_Q
)
let pts = isPointer(avframe)
? avRescaleQ2(
avframe.pts,
addressof(avframe.timeBase),
AV_TIME_BASE_Q
)
: static_cast<int64>((avframe as VideoFrame).timestamp as uint32)

if (pts < this.options.start) {
while (true) {
Expand All @@ -54,11 +56,13 @@ export default class RangeFilterNode extends AVFilterNode {
outputs[0] = next
return
}
pts = avRescaleQ(
isPointer(next) ? next.pts : static_cast<int64>(next.timestamp as uint32),
isPointer(next) ? next.timeBase : AV_TIME_BASE_Q,
AV_TIME_BASE_Q
)
pts = isPointer(next)
? avRescaleQ2(
next.pts,
addressof(next.timeBase),
AV_TIME_BASE_Q
)
: static_cast<int64>(next.timestamp as uint32)
if (pts >= this.options.start) {
outputs[0] = next
return
Expand Down
26 changes: 15 additions & 11 deletions src/avfilter/video/FramerateFilterNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import AVFrame, { AVFrameRef } from 'avutil/struct/avframe'
import * as is from 'common/util/is'
import { createAVFrame, destroyAVFrame, refAVFrame } from 'avutil/util/avframe'
import { Rational } from 'avutil/struct/rational'
import { avRescaleQ } from 'avutil/util/rational'
import { avRescaleQ, avRescaleQ2 } from 'avutil/util/rational'
import { AV_TIME_BASE_Q } from 'avutil/constant'
import isPointer from 'cheap/std/function/isPointer'

Expand Down Expand Up @@ -51,11 +51,13 @@ export default class FramerateFilterNode extends AVFilterNode {
return
}

let pts = avRescaleQ(
isPointer(avframe) ? avframe.pts : static_cast<int64>((avframe as VideoFrame).timestamp),
isPointer(avframe) ? avframe.timeBase : AV_TIME_BASE_Q,
this.timeBase
)
let pts = isPointer(avframe)
? avRescaleQ2(
avframe.pts,
addressof(avframe.timeBase),
this.timeBase
)
: static_cast<int64>((avframe as VideoFrame).timestamp)
let diff = pts - this.lastPts + this.delta

if (diff < this.step && this.lastPts > -1n) {
Expand All @@ -65,11 +67,13 @@ export default class FramerateFilterNode extends AVFilterNode {
outputs[0] = next
return
}
pts = avRescaleQ(
isPointer(next) ? next.pts : static_cast<int64>(next.timestamp),
isPointer(next) ? next.timeBase : AV_TIME_BASE_Q,
this.timeBase
)
pts = isPointer(next)
? avRescaleQ2(
next.pts,
addressof(next.timeBase),
this.timeBase
)
: static_cast<int64>(next.timestamp)
diff = pts - this.lastPts
if (diff >= this.step) {
this.delta += diff - this.step
Expand Down
14 changes: 7 additions & 7 deletions src/avformat/demux.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { AV_MILLI_TIME_BASE_Q, NOPTS_VALUE_BIGINT } from 'avutil/constant'
import { AVPacketSideDataType, AVCodecID, AVMediaType } from 'avutil/codec'
import { AVFormat, AVSeekFlags, IOFlags } from 'avutil/avformat'
import { checkStreamParameters } from './function/checkStreamParameters'
import { avRescaleQ } from 'avutil/util/rational'
import { avRescaleQ, avRescaleQ2 } from 'avutil/util/rational'
import { copyAVPacketData, createAVPacket, destroyAVPacket,
getAVPacketSideData,
hasAVPacketSideData, refAVPacket, unrefAVPacket
Expand Down Expand Up @@ -604,24 +604,24 @@ async function packetNeedRead(formatContext: AVIFormatContext, avpacket: pointer

if (!stream.sampleIndexes.length
|| (index < 0
&& avRescaleQ(
&& avRescaleQ2(
avpacket.pts - stream.sampleIndexes[stream.sampleIndexes.length - 1].pts,
avpacket.timeBase,
addressof(avpacket.timeBase),
AV_MILLI_TIME_BASE_Q
) >= SAMPLE_INDEX_STEP
)
|| (index > 0
&& index < stream.sampleIndexes.length - 1
&& avRescaleQ(
&& avRescaleQ2(
avpacket.pts - stream.sampleIndexes[index - 1].pts,
avpacket.timeBase,
addressof(avpacket.timeBase),
AV_MILLI_TIME_BASE_Q
) >= SAMPLE_INDEX_STEP
)
|| (index === 0
&& avRescaleQ(
&& avRescaleQ2(
stream.sampleIndexes[0].pts - avpacket.pts,
avpacket.timeBase,
addressof(avpacket.timeBase),
AV_MILLI_TIME_BASE_Q
) >= SAMPLE_INDEX_STEP
)
Expand Down
2 changes: 1 addition & 1 deletion src/avformat/formats/IRtspFormat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import RTPFrameQueue from 'avprotocol/rtp/RTPFrameQueue'
import * as depacketizer from 'avprotocol/rtp/depacketizer'
import * as naluUtil from 'avutil/util/nalu'
import { avRescaleQ } from 'avutil/util/rational'
import { AV_MILLI_TIME_BASE_Q, AV_TIME_BASE_Q, NOPTS_VALUE, NOPTS_VALUE_BIGINT, NTP_OFFSET_US } from 'avutil/constant'
import { AV_TIME_BASE_Q, NOPTS_VALUE, NOPTS_VALUE_BIGINT, NTP_OFFSET_US } from 'avutil/constant'
import isRtcp from 'avprotocol/rtcp/isRtcp'
import isRtp from 'avprotocol/rtp/isRtp'
import { parseRTPPacket } from 'avprotocol/rtp/parser'
Expand Down
18 changes: 9 additions & 9 deletions src/avformat/formats/OFlvFormat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import { AVFormat } from 'avutil/avformat'
import { mapUint8Array } from 'cheap/std/memory'
import * as logger from 'common/util/logger'
import { createAVPacket, destroyAVPacket, getAVPacketSideData } from 'avutil/util/avpacket'
import { avQ2D, avRescaleQ } from 'avutil/util/rational'
import { avQ2D, avRescaleQ2 } from 'avutil/util/rational'
import Annexb2AvccFilter from '../bsf/h2645/Annexb2AvccFilter'
import { BitFormat } from 'avutil/codecs/h264'
import { NOPTS_VALUE_BIGINT } from 'avutil/constant'
Expand Down Expand Up @@ -269,7 +269,7 @@ export default class OFlvFormat extends OFormat {
formatContext.ioWriter,
FlvTag.AUDIO,
avpacket.size + 1 + FlvCodecHeaderLength[stream.codecpar.codecId],
avRescaleQ(avpacket.dts, avpacket.timeBase, stream.timeBase)
avRescaleQ2(avpacket.dts, addressof(avpacket.timeBase), stream.timeBase)
)

oflv.writeAudioTagDataHeader(formatContext.ioWriter, stream)
Expand All @@ -285,7 +285,7 @@ export default class OFlvFormat extends OFormat {

this.context.audioSize += previousTagSize
this.context.filesize += previousTagSize + 4
this.context.lasttimestamp = avRescaleQ(avpacket.pts, avpacket.timeBase, stream.timeBase)
this.context.lasttimestamp = avRescaleQ2(avpacket.pts, addressof(avpacket.timeBase), stream.timeBase)
this.context.datasize += avpacket.size || 0
}
}
Expand Down Expand Up @@ -350,7 +350,7 @@ export default class OFlvFormat extends OFormat {
FlvTag.VIDEO,
avpacket.size + 1 + FlvCodecHeaderLength[stream.codecpar.codecId]
+ (packetType === PacketTypeExt.PacketTypeCodedFrames ? 3 : 0),
avRescaleQ(avpacket.dts, avpacket.timeBase, stream.timeBase)
avRescaleQ2(avpacket.dts, addressof(avpacket.timeBase), stream.timeBase)
)
oflv.writeVideoTagExtDataHeader(formatContext.ioWriter, stream, packetType, avpacket.flags)

Expand All @@ -359,7 +359,7 @@ export default class OFlvFormat extends OFormat {
if (packetType === PacketTypeExt.PacketTypeCodedFrames) {
let ct = 0
if (avpacket.pts !== NOPTS_VALUE_BIGINT) {
ct = static_cast<int32>(avRescaleQ(avpacket.pts - avpacket.dts, avpacket.timeBase, stream.timeBase))
ct = static_cast<int32>(avRescaleQ2(avpacket.pts - avpacket.dts, addressof(avpacket.timeBase), stream.timeBase))
}
formatContext.ioWriter.writeUint24(ct)
}
Expand All @@ -369,7 +369,7 @@ export default class OFlvFormat extends OFormat {
formatContext.ioWriter,
FlvTag.VIDEO,
avpacket.size + 1 + FlvCodecHeaderLength[stream.codecpar.codecId],
avRescaleQ(avpacket.dts, avpacket.timeBase, stream.timeBase)
avRescaleQ2(avpacket.dts, addressof(avpacket.timeBase), stream.timeBase)
)
if (stream.codecpar.codecId === AVCodecID.AV_CODEC_ID_H264
|| stream.codecpar.codecId === AVCodecID.AV_CODEC_ID_MPEG4
Expand All @@ -378,7 +378,7 @@ export default class OFlvFormat extends OFormat {

let ct = 0
if (avpacket.pts !== NOPTS_VALUE_BIGINT) {
ct = static_cast<int32>(avRescaleQ(avpacket.pts - avpacket.dts, avpacket.timeBase, stream.timeBase))
ct = static_cast<int32>(avRescaleQ2(avpacket.pts - avpacket.dts, addressof(avpacket.timeBase), stream.timeBase))
}
flvH264.writeDataHeader(formatContext.ioWriter, AVCPacketType.AVC_NALU, ct)
}
Expand All @@ -391,13 +391,13 @@ export default class OFlvFormat extends OFormat {

this.context.videosize += previousTagSize
this.context.filesize += previousTagSize + 4
this.context.lasttimestamp = avRescaleQ(avpacket.pts, avpacket.timeBase, stream.timeBase)
this.context.lasttimestamp = avRescaleQ2(avpacket.pts, addressof(avpacket.timeBase), stream.timeBase)
this.context.datasize += avpacket.size || 0
this.context.frameCount++

if (avpacket.flags & AVPacketFlags.AV_PKT_FLAG_KEY) {
if (this.context.firstKeyframePositionWrote || !this.context.videoMetadataWrote) {
this.context.lastkeyframetimestamp = avRescaleQ(avpacket.pts, avpacket.timeBase, stream.timeBase)
this.context.lastkeyframetimestamp = avRescaleQ2(avpacket.pts, addressof(avpacket.timeBase), stream.timeBase)
this.context.lastkeyframelocation = Number(keyframePos)
this.context.keyFrameTimes.push(Number((Number(this.context.lastkeyframetimestamp) * avQ2D(stream.timeBase)).toFixed(2)))
this.context.keyframeFilePositions.push(this.context.lastkeyframelocation)
Expand Down
4 changes: 2 additions & 2 deletions src/avformat/formats/OIvfFormat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import OFormat from './OFormat'
import { AVMediaType } from 'avutil/codec'
import { AVFormat } from 'avutil/avformat'
import * as logger from 'common/util/logger'
import { avRescaleQ } from 'avutil/util/rational'
import { avRescaleQ2 } from 'avutil/util/rational'
import { getAVPacketData } from 'avutil/util/avpacket'

export const enum IVFCodec {
Expand Down Expand Up @@ -132,7 +132,7 @@ export default class OIVFFormat extends OFormat {
const stream = formatContext.getStreamByMediaType(AVMediaType.AVMEDIA_TYPE_VIDEO)
if (stream) {
formatContext.ioWriter.writeUint32(avpacket.size)
formatContext.ioWriter.writeUint64(avRescaleQ(avpacket.pts || avpacket.dts, avpacket.timeBase, stream.timeBase))
formatContext.ioWriter.writeUint64(avRescaleQ2(avpacket.pts || avpacket.dts, addressof(avpacket.timeBase), stream.timeBase))
formatContext.ioWriter.writeBuffer(getAVPacketData(avpacket))
this.header.framesCount++
}
Expand Down
10 changes: 5 additions & 5 deletions src/avformat/formats/OMatroskaFormat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import OFormat from './OFormat'
import { AVCodecID, AVMediaType, AVPacketSideDataType } from 'avutil/codec'
import { AVFormat } from 'avutil/avformat'
import * as logger from 'common/util/logger'
import { avRescaleQ } from 'avutil/util/rational'
import { avRescaleQ2 } from 'avutil/util/rational'
import { createAVPacket, destroyAVPacket, getAVPacketData, getAVPacketSideData, hasAVPacketSideData } from 'avutil/util/avpacket'
import * as object from 'common/util/object'
import { OMatroskaContext, TrackEntry } from './matroska/type'
Expand Down Expand Up @@ -356,7 +356,7 @@ export default class OMatroskaFormat extends OFormat {
}
omatroska.writeEbmlLength(this.context.eleWriter, omatroska.ebmlLengthSize(track.number) + 2 + 1 + avpacket.size)
omatroska.writeEbmlNum(this.context.eleWriter, track.number, omatroska.ebmlLengthSize(track.number))
const pts = avRescaleQ(avpacket.pts, avpacket.timeBase, AV_MILLI_TIME_BASE_Q)
const pts = avRescaleQ2(avpacket.pts, addressof(avpacket.timeBase), AV_MILLI_TIME_BASE_Q)

this.context.eleWriter.writeInt16(static_cast<int32>(pts - this.context.currentCluster.timeCode))

Expand All @@ -382,7 +382,7 @@ export default class OMatroskaFormat extends OFormat {
private writeBlockGroup(stream: AVStream, avpacket: pointer<AVPacket>) {
omatroska.writeEleData(this.context.eleWriter, this.context, EBMLId.BLOCK_GROUP, (eleWriter) => {
if (avpacket.duration > 0) {
omatroska.writeEbmlUint(eleWriter, EBMLId.BLOCK_DURATION, avRescaleQ(avpacket.duration, avpacket.timeBase, AV_MILLI_TIME_BASE_Q))
omatroska.writeEbmlUint(eleWriter, EBMLId.BLOCK_DURATION, avRescaleQ2(avpacket.duration, addressof(avpacket.timeBase), AV_MILLI_TIME_BASE_Q))
}
const additions: {
additionalId: int64
Expand Down Expand Up @@ -454,13 +454,13 @@ export default class OMatroskaFormat extends OFormat {

const track = stream.privData as TrackEntry

const pts = avRescaleQ(avpacket.pts !== NOPTS_VALUE_BIGINT ? avpacket.pts : avpacket.dts, avpacket.timeBase, AV_MILLI_TIME_BASE_Q)
const pts = avRescaleQ2(avpacket.pts !== NOPTS_VALUE_BIGINT ? avpacket.pts : avpacket.dts, addressof(avpacket.timeBase), AV_MILLI_TIME_BASE_Q)

if (!track.maxPts || track.maxPts < pts) {
track.maxPts = pts
track.duration = pts
if (avpacket.duration !== NOPTS_VALUE_BIGINT) {
track.duration += avRescaleQ(avpacket.duration, avpacket.timeBase, AV_MILLI_TIME_BASE_Q)
track.duration += avRescaleQ2(avpacket.duration, addressof(avpacket.timeBase), AV_MILLI_TIME_BASE_Q)
}
}

Expand Down
Loading

0 comments on commit f7e293a

Please sign in to comment.