Skip to content

Commit

Permalink
Merge pull request #36 from Lumen5/seekingFix2
Browse files Browse the repository at this point in the history
Another seeking fix
  • Loading branch information
animanathome authored May 12, 2023
2 parents 22225ea + 625ea05 commit e23da4a
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 5 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@lumen5/framefusion",
"version": "0.0.18",
"version": "0.0.19",
"type": "module",
"scripts": {
"docs": "typedoc framefusion.ts",
Expand Down
19 changes: 15 additions & 4 deletions src/backends/beamcoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,12 @@ export class BeamcoderExtractor extends BaseExtractor implements Extractor {
*/
#streamIndex = 0;

/**
* The number of packets we've read from the demuxer to complete the frame query
* @private
*/
#packetReadCount = 0;

/**
* Encoder/Decoder construction is async, so it can't be put in a regular constructor.
* Use and await this method to generate an extractor.
Expand Down Expand Up @@ -272,12 +278,16 @@ export class BeamcoderExtractor extends BaseExtractor implements Extractor {
return pts * time_base[0] / time_base[1];
}

get packetReadCount() {
return this.#packetReadCount;
}

/**
* Get the frame at the given presentation timestamp (PTS)
*/
async _getFrameAtPts(targetPTS: number) {
VERBOSE && console.log('_getFrameAtPts', targetPTS, '-> duration', this.duration);
let packetReadCount = 0;
this.#packetReadCount = 0;

// seek and create a decoder when retrieving a frame for the first time or when seeking backwards
// we have to create a new decoder when seeking backwards as the decoder can only process frames in
Expand Down Expand Up @@ -306,13 +316,14 @@ export class BeamcoderExtractor extends BaseExtractor implements Extractor {
VERBOSE && console.log('returning previously filtered frame with pts', (closestFrame as Frame).pts);
closestFramePTS = (closestFrame as Frame).pts;
outputFrame = closestFrame;
this.#previousTargetPTS = targetPTS;
}
}

// This is the first time we're decoding frames. Get the first packet and decode it.
if (!this.#packet && this.#frames.length === 0) {
({ packet: this.#packet, frames: this.#frames } = await this._getNextPacketAndDecodeFrames());
packetReadCount++;
this.#packetReadCount++;
}
// Read packets until we have a frame which is closest to targetPTS
while ((this.#packet || this.#frames.length !== 0) && closestFramePTS < targetPTS) {
Expand Down Expand Up @@ -360,13 +371,13 @@ export class BeamcoderExtractor extends BaseExtractor implements Extractor {
({ packet: this.#packet, frames: this.#frames } = await this._getNextPacketAndDecodeFrames());

// keep track of how many packets we've read
packetReadCount++;
this.#packetReadCount++;
}

if (!outputFrame) {
throw Error('No matching frame found');
}
VERBOSE && console.log('read', packetReadCount, 'packets');
VERBOSE && console.log('read', this.packetReadCount, 'packets');

this.#previousTargetPTS = targetPTS;
return outputFrame;
Expand Down
18 changes: 18 additions & 0 deletions test/framefusion.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,24 @@ describe('FrameFusion', () => {
await extractor.dispose();
});

it('only reads a few packets to get the next frame after a seek', async() => {
const extractor = await BeamcoderExtractor.create({
inputFileOrUrl: 'https://storage.googleapis.com/lumen5-prod-video/mvc-4k-new-orleans-a053c0340725rv-112014WA74Rf.mp4',
});

const offset = 1.0 * FPS;
for (let i = offset; i < offset + 10; i++) {
const time = i / FPS + FRAME_SYNC_DELTA;
await extractor.getFrameAtTime(time);

// for the first frame query we have to find the closest PTS and read several packets to get the closest
// frame, after that we should only have to read a few packets
if (i > offset + 2) {
expect(extractor.packetReadCount).to.equal(1);
}
}
});

it('can identify video stream index', async() => {
// Arrange
const extractor = await BeamcoderExtractor.create({
Expand Down

0 comments on commit e23da4a

Please sign in to comment.