Skip to content

Conversation

@SomeBody16
Copy link
Contributor

@SomeBody16 SomeBody16 commented Sep 25, 2025

COMPLETES SPARK-728169

This pull request addresses

The need to add AV1 codec support to the Webex JS SDK multistream functionality. AV1 (AOMedia Video 1) is a modern, open-source video codec that provides superior compression efficiency compared to H.264, enabling better video quality at lower bitrates. This enhancement allows the SDK to leverage AV1 codec capabilities for improved video streaming performance in multistream scenarios.

by making the following changes

Architecture Improvements

  • Introduced Codec Helper Pattern: Created a factory-based architecture for handling different video codecs (AV1 and H.264) through dedicated helper classes
    • MediaCodecHelper - Abstract base class defining the codec helper interface
    • MediaCodecHelperAV1 - AV1-specific implementation with maxPicSize and frame size calculations
    • MediaCodecHelperH264 - H.264-specific implementation maintaining existing behavior
    • MediaCodecHelperFactory - Factory class for creating appropriate codec helpers

Core Functionality

  • AV1 Codec Support: Added comprehensive AV1 codec parameter handling including:

    • Level index, tier, maxWidth, maxHeight, maxPicSize, and maxDecodeRate parameters
    • Picture size to frame size conversion (rounded to 16x16 macroblock units)
    • Resolution-specific AV1 codec parameters for 180p, 360p, 540p, 720p, and 1080p
    • Integration with @webex/internal-media-core AV1Codec class
  • Enhanced Media Request Manager: Refactored mediaRequestManager.ts to:

    • Support codec-specific media request degradation
    • Handle maxPicSize updates dynamically
    • Improve resolution handling across different codecs
    • Reduce complexity by delegating codec-specific logic to helper classes
  • Remote Media Enhancements: Updated remote media handling to:

    • Support new remote video resolutions with codec-aware constraints
    • Handle maxPicSize changes in media requests
    • Improved receive slot management with codec-specific parameters

Code Quality

  • Type Safety: Added comprehensive TypeScript types for AV1 codec info and parameters
  • Constants Organization: Consolidated codec-related constants in a dedicated constants file
  • Test Coverage: Added 600+ lines of new unit tests covering:
    • Media request manager with AV1 codec scenarios
    • Remote media group functionality
    • Remote media manager behavior
    • Utility functions for codec handling

Package Updates

  • Updated @webex/media-helpers and @webex/plugin-meetings package versions
  • Cleaned up unused dependencies in yarn.lock

Change Type

  • New feature (non-breaking change which adds functionality)
  • Internal code refactor

The following scenarios were tested

Automated Tests

  • ✅ All existing unit tests pass
  • ✅ New unit tests added for:
    • AV1 codec helper functionality (codec info generation, media request degradation, bitrate calculations)
    • Media request manager with AV1 codec support (maxPicSize handling, resolution degradation)
    • Remote media group with AV1 parameters
    • Remote media manager with codec-specific behavior
    • Utility functions for picSize calculations and frame size conversions

Manual Testing

  • ✅ Verified AV1 codec parameter selection based on maxPicSize constraints
  • ✅ Tested media request degradation with different resolution levels (180p-1080p)
  • ✅ Validated maxPicSize updates propagate correctly through the system
  • ✅ Confirmed backward compatibility with existing H.264 codec flows
  • ✅ Tested codec factory correctly instantiates appropriate helper classes

Integration Scenarios

  • ✅ Media request creation with AV1 codec info
  • ✅ Dynamic resolution changes during active multistream sessions
  • ✅ MaxPicSize enforcement when receiving video streams
  • ✅ WCME codec info generation for AV1 streams

The GAI Coding Policy And Copyright Annotation Best Practices

  • GAI was not used (or, no additional notation is required)
  • Code was generated entirely by GAI
  • GAI was used to create a draft that was subsequently customized or modified
  • Coder created a draft manually that was non-substantively modified by GAI (e.g., refactoring was performed by GAI on manually written code)
  • Tool used for AI assistance (GitHub Copilot / Other - specify)
    • Github Copilot
    • Other - Please Specify
  • This PR is related to
    • Feature
    • Defect fix
    • Tech Debt
    • Automation

I certified that

  • I have read and followed contributing guidelines
  • I discussed changes with code owners prior to submitting this pull request
  • I have not skipped any automated checks
  • All existing and new tests passed
  • I have updated the documentation accordingly

Summary Statistics

  • Files Changed: 23 files
  • Lines Added: ~2,087
  • Lines Removed: ~686
  • Net Impact: +1,401 lines
  • New Test Coverage: 1,000+ lines of unit tests

Make sure to have followed the contributing guidelines before submitting.

@SomeBody16 SomeBody16 changed the title feat: av1 attempt feat: av1 Sep 25, 2025
Comment on lines 236 to 239
codecInfo: mediaCodecHelper.getCodecInfo({
maxFs: this.getEffectiveMaxFs(),
maxPicSize: this.getEffectiveMaxPicSize(),
}),
Copy link
Contributor

@antsukanova antsukanova Oct 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should not be possible that maxFs and maxPicSize will be passed at the same time, right? Thinking in the way that I feel, here we need to think about more abstract passing data according to what codec we are currently working with.

Something like

codecInfo = helper.getCodecInfo(this.buildCodecConstraints());

private buildCodecConstraints(): CodecConstraints {
  const codec = this.options.preferredCodec;
  if (codec === 'av1') {
    const maxPicSize = this.getEffectiveMaxPicSize();
    return maxPicSize ? {maxPicSize} : {};
  }
  // default h264 or do if for h264
  const maxFs = this.getEffectiveMaxFs();
  return maxFs ? {maxFs} : {};
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is tricky because at one side I want to delegate all codec checks to mediaCodecHelper but at the same time here we need different info for different codecs

Maybe solution would be instead of calling two getEffectiveX() methods to pass references to it?

const codecInfo = mediaCodecHelper.getCodecInfo({
    maxFs: () => this.getEffectiveMaxFs(),
    maxPicSize: () => this.getEffectiveMaxPicSize(),
})

So won't calculate useless stuff but av1/h264 will call method that they want to use?

export type {
/** @deprecated use CodecInfo from @webex/plugin-meetings/src/codec/types instead */
CodecInfo,
} from './codec/types';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because this types are used by children repositories, we need to have backward compatibility for them.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this is the correct way to deprecate things for the SDK. Should we take care to update this or at least create a task for such changes? Could the SDK team address these deprecations?

},
'1080p': {
maxPicSize: 2_359_296,
levelIdx: 9,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So far, I believe @k-wasniowski said that we won't support the different levelIdx, ot I'm missing something?


return [
WcmeCodecInfo.fromAv1(
45,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we have any constant for this param here?

resolution = PANE_SIZE_TO_RESOLUTION[paneSize];
} else {
LoggerProxy.logger.warn(
`MediaCodecHelperAV1#getMaxPicSize --> unsupported paneSize: ${paneSize}, using "medium" instead`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: you can use in log PANE_SIZE_TO_RESOLUTION.medium

Comment on lines +42 to +44
if (mr.codecInfo?.codec !== 'h264') {
return 0;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if returning 0 silently is good idea here for an incorrect codec. It would be good to log info that unexpected mr.codecInfo?.codec is passed here.

export type {
/** @deprecated use CodecInfo from @webex/plugin-meetings/src/codec/types instead */
CodecInfo,
} from './codec/types';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this is the correct way to deprecate things for the SDK. Should we take care to update this or at least create a task for such changes? Could the SDK team address these deprecations?


type ClientRequestsMap = {[key: MediaRequestId]: MediaRequest};

// eslint-disable-next-line import/prefer-default-export
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need this comment for ESLint? It wasn't here before

Comment on lines +28 to +31
getCodecInfo(options: {
getMaxFs?: () => number;
getMaxPicSize?: () => number;
}): CodecInfo | undefined;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel we need to improve this part here...The shared signature in MediaCodecHelper forces every helper to accept both getMaxFs and getMaxPicSize, even though only one makes sense per codec.
Can we have here generic helper interface for getCodecInfo and export concrete types MediaCodecHelperH264?

something like

interface MediaCodecHelper<TOptions, TCodecInfo> {getCodecInfo(options: TOptions): TCodecInfo | undefined; ... }

Comment on lines +196 to +199
codecInfo: mediaCodecHelper.getCodecInfo({
getMaxFs: () => this.getEffectiveMaxFs(),
getMaxPicSize: () => this.getEffectiveMaxPicSize(),
}),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have here after generic helper interface for getCodecInfo impromevents something like:

const codecInfo =
  mediaCodecHelper.codec === 'h264'
    ? mediaCodecHelper.getCodecInfo({getMaxFs: () => this.getEffectiveMaxFs()})
    : mediaCodecHelper.getCodecInfo({getMaxPicSize: () => this.getEffectiveMaxPicSize()});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants