AV1编码及AV1的码流结构

AV1的码流结构

AV1码流由OBU(Open Bitstream Unit)码流单元组成,OBU的结构如下所示。

--------------------------------------
obu_header | *obu_size | obu_payload |
--------------------------------------
  • obu_size指的是obu_payload的字节大小。
  • obu_size不是必须的,由obu_header中的obu_has_size_field字段标识是否存在,不存在时需要由外部告知OBU的大小。
  • 标准[1]中定义的“Low overhead bitstream format”格式要求obu_has_size_field必须为1。
  • 对于需要更容易跳过帧或时间单位的格式的应用程序,[1]定义了Annex B长度分隔的码流格式,obu_has_size_field不为1。
  • 派生的规范,例如支持存储AV1视频的容器格式,应该指出它们所依赖的是哪种格式。
  • 其他打包OBUs视频流的方法也是允许的。

enum

{

OBU_SEQUENCE_HEADER = 1,

OBU_TEMPORAL_DELIMITER = 2,

OBU_FRAME_HEADER = 3,

OBU_TILE_GROUP = 4,

OBU_METADATA = 5,

OBU_FRAME = 6,

OBU_REDUNDANT_FRAME_HEADER = 7,

OBU_TILE_LIST = 8,

// 9-14 Reserved

OBU_PADDING = 15,

};

obu_type取值

图片

AV1的编码

aom_img_alloc():为结构体aom_image_t分配内存,用于存储未编码压缩的图像数据。API说明:

  • aom_codec_enc_config_default():设置参数集结构体aom_codec_enc_cfg_t的默认值。
  • aom_codec_enc_init:打开编码器,编码完成之后需使用aom_codec_destroy()关闭编码器。
  • ivf_write_header:写IVF封装格式的文件头。
  • aom_codec_encode():编码一帧图像。
  • aom_codec_get_cx_data():获取一帧压缩编码数据,数据存储在返回的aom_codec_cx_pkt_t结构体中。
  • ivf_write_frame():写IVF封装格式的文每帧数据。

#include "av1-encoder.h"
#if defined(ENABLE_AV1)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdbool.h>
#include <aom/aom_image.h>
#include <aom/aom.h>
#include <aom/aom_encoder.h>
#include <aom/aomcx.h>
#include <aom/aom_encoder.h>
#include <aom/aom_codec.h>
#include <aom/aomcx.h>
#include <math.h>       /* log2 */
//#include <iostream>
//using namespace std;
//aomenc.exe -c -i ...1920x1080.yuv -w 1920 -h 1080 --limit=10 --verbose --psnr -o rec.bin
// 右键打开aomenc的属性,在调试里输入--width=1280 --height=720 --end-usage=cq --min-q=27 --max-q=35 --min-gf-interval=4 --max-gf-interval=4 --cpu-used=4 --threads=16 --limit=12 -o --width=1280 --height=720 --end-usage=cq --min-q=27 --max-q=35 --min-gf-interval=4 --max-gf-interval=4 --cpu-used=4 --threads=16 --limit=12 -o d://1920x1080.ivf  d://1280x720.yuv
// --width=1920 --height=1080 --end-usage=cq --min-q=27 --max-q=35 --min-gf-interval=4 --max-gf-interval=4 --cpu-used=4 --threads=16 --limit=12 -o --width=1920 --height=1080 --end-usage=cq --min-q=27 --max-q=35 --min-gf-interval=4 --max-gf-interval=4 --cpu-used=4 --threads=16 --limit=12 -o d://1920x1080.ivf  d://1920x1080.yuv
//blog.csdn.net/qq_30945147/article/details/94597226
//aomenc.exe --width=352 --height=288 --end-usage=cq --min-q=27 --max-q=35 --min-gf-interval=4 --max-gf-interval=4 --cpu-used=4 --threads=16 --limit=12 -o Test5.ivf foreman_cif.yuv
//av1 1280 720 d://1280x720.yuv d://1920x1080.ivf 25 0 30
struct xav_encoder_t
{
  aom_img_fmt_t imageFormat;
  aom_image_t image;
  aom_codec_enc_cfg_t configuration;
  aom_codec_ctx_t codec;

  uint32_t width, height;
  uint32_t maxencodetime;
  size_t bytes;
};
#define MINQ 0
#define MAXQ 255
#define QINDEX_RANGE (MAXQ - MINQ + 1)
#define QINDEX_BITS 8
// Total number of QM sets stored
#define QM_LEVEL_BITS 4
#define NUM_QM_LEVELS (1 << QM_LEVEL_BITS)
/* Range of QMS is between first and last value, with offset applied to inter
 * blocks*/
#define DEFAULT_QM_Y 10
#define DEFAULT_QM_U 11
#define DEFAULT_QM_V 12
#define DEFAULT_QM_FIRST 5
#define DEFAULT_QM_LAST 9
#define LOSSLESS_Q_STEP 4  // this should equal to dc/ac_qlookup_QTX[0]
enum {
  NO_AQ = 0,
  VARIANCE_AQ = 1,
  COMPLEXITY_AQ = 2,
  CYCLIC_REFRESH_AQ = 3,
  AQ_MODE_COUNT  // This should always be the last member of the enum
} UENUM1BYTE(AQ_MODE);
enum {
  NO_DELTA_Q = 0,
  DELTA_Q_OBJECTIVE = 1,      // Modulation to improve objective quality
  DELTA_Q_PERCEPTUAL = 2,     // Modulation to improve video perceptual quality
  DELTA_Q_PERCEPTUAL_AI = 3,  // Perceptual quality opt for all intra mode
  DELTA_Q_MODE_COUNT  // This should always be the last member of the enum
} UENUM1BYTE(DELTAQ_MODE);

static void modify(aom_codec_ctx_t* aom) {

  uint8_t colorPrimaries = 1;
  uint8_t transferCharacteristics = 13;
  uint8_t matrixCoefficients = 1;
  int crf = 10;
  int deltaQMode = 0;
  bool enableChromaDeltaQ = false;
  bool enableDeltaLoopfilter = false;
  bool useQM = false;
  int qmMin = DEFAULT_QM_FIRST;
  int qmMax = DEFAULT_QM_LAST;
  int qmMinY = DEFAULT_QM_Y;
  int qmMinU = DEFAULT_QM_U;
  int qmMinV = DEFAULT_QM_V;
  bool enableRectPartition = true;
  bool enableABPartition = true;
  bool enable1to4Partition = true;
  int minPartitionSize = 4;
  int maxPartitionSize = 128;
  bool rowMT = false;
  int cpuUsed = 1;
  int sharpness = 0;
  int tileRows = 0;
  int tileColumns = 0;
  int keyframeTemporalFilter = 0;
  bool enableIntraEdgeFilter = true;
  bool enableTX64 = true;
  bool enableFlipIDTX = true;
  bool enableRectTX = true;
  bool useDCTOnly = false;
  bool useDefaultTXOnly = false;
  bool useReducedTXSet = false;
  int adaptiveQuantizationMode = NO_AQ;
  bool enableAdaptiveQuantizationB = false;
  bool enableFilterIntra = true;
  bool enableSmoothIntra = true;
  bool enablePaethIntra = true;
  bool enableChromaFromLuma = true;
  bool enableSuperres = true;
  bool enablePalette = false;
  bool enableIntraBC = true;
  bool enableAngleDelta = true;
  bool lossless = false;
  bool enableCDEF = false;
  bool enableRestoration = false;
  bool fullColorRange = false;
  aom_superblock_size_t superblockSize = AOM_SUPERBLOCK_SIZE_DYNAMIC;
  aom_tune_metric tune = AOM_TUNE_SSIM;

#define set(param, expr) 
    if(aom_codec_control(aom, param, (expr)) != AOM_CODEC_OK) { 
      printf("Failed to set  n") ; 
    }

  //(void)AOME_USE_REFERENCE; // It's for movies?

  //FIXME: not implemented yet at libaom.
  // It can be useful for manga images.
  //aom_codec_control(codec, AOME_SET_ROI_MAP, ...);

  (void)AOME_SET_ACTIVEMAP; // for internal use only
  /*if (!(scaleMode.h_scaling_mode == AOME_NORMAL && scaleMode.v_scaling_mode == AOME_NORMAL)) {
    set(AOME_SET_SCALEMODE, &scaleMode);
  }*/
  (void)AOME_SET_SPATIAL_LAYER_ID; // for adaptive video decoding (such as for Netflix or Youtube).
  set(AOME_SET_CPUUSED, cpuUsed);
  set(AOME_SET_SHARPNESS, sharpness);
  (void)AOME_SET_ENABLEAUTOALTREF; // is used only in 2nd pass(thus, is's for video).
  (void)AOME_SET_ENABLEAUTOBWDREF; // is for video (bwd-pred frames).
  (void)AOME_SET_STATIC_THRESHOLD; // is for video.
  (void)AOME_SET_ARNR_MAXFRAMES; // is for video.
  (void)AOME_SET_ARNR_STRENGTH; // is for video.
  set(AOME_SET_TUNING, tune);
  set(AOME_SET_CQ_LEVEL, crf);
  // It always can be 0(unlimited) for AVIF.
  set(AOME_SET_MAX_INTRA_BITRATE_PCT, 0);
  (void)AOME_SET_NUMBER_SPATIAL_LAYERS; // for video
  (void)AV1E_SET_MAX_INTER_BITRATE_PCT; // for video
  (void)AV1E_SET_GF_CBR_BOOST_PCT; // for video.(I don't know what Golden Frame is)
  set(AV1E_SET_LOSSLESS, lossless ? 1 : 0);
  set(AV1E_SET_ROW_MT, rowMT ? 1 : 0);
  set(AV1E_SET_TILE_ROWS, tileRows);
  set(AV1E_SET_TILE_COLUMNS, tileColumns);
  (void)AV1E_SET_ENABLE_TPL_MODEL; // is for video.
  set(AV1E_SET_ENABLE_KEYFRAME_FILTERING, keyframeTemporalFilter);
  (void)AV1E_SET_FRAME_PARALLEL_DECODING; // is for video. we have just one frame.
  (void)AV1E_SET_ERROR_RESILIENT_MODE; // is for video.
  (void)AV1E_SET_S_FRAME_MODE; // is for video.
  set(AV1E_SET_AQ_MODE, adaptiveQuantizationMode);
  (void)AV1E_SET_FRAME_PERIODIC_BOOST; // is for video.

  //FIXME(ledyba-z): it can be set, but not used.
  // To check, `grep -R 'oxcf->noise_sensitivity' external/libaom/av1`
  // control(AV1E_SET_NOISE_SENSITIVITY, 0);

  //FIXME(ledyba-z): it can be set, but not used.
  // To check, `grep -R 'oxcf->content' external/libaom/av1`
  // control(AV1E_SET_TUNE_CONTENT, AOM_CONTENT_DEFAULT);

  (void)AV1E_SET_CDF_UPDATE_MODE; // is for video.

  //FIXME(ledyba-z): support color profile. PNG can contain gamma correction and color profile.
  // Gamma Correction and Precision Color (PNG: The Definitive Guide)
  // http://www.libpng.org/pub/png/book/chapter10.html
  //
  set(AV1E_SET_COLOR_PRIMARIES, colorPrimaries);
  set(AV1E_SET_TRANSFER_CHARACTERISTICS, transferCharacteristics);
  set(AV1E_SET_MATRIX_COEFFICIENTS, matrixCoefficients);

  set(AV1E_SET_CHROMA_SAMPLE_POSITION, 0); // see libavif-container

  (void)AV1E_SET_MIN_GF_INTERVAL; // for video
  set(AV1E_SET_COLOR_RANGE, fullColorRange ? 1 : 0);
  (void)AV1E_SET_RENDER_SIZE; // should be the same as the output size. It's default.

  (void)AV1E_SET_TARGET_SEQ_LEVEL_IDX; // for video.
  set(AV1E_SET_SUPERBLOCK_SIZE, superblockSize);
  (void)AOME_SET_ENABLEAUTOBWDREF; // is for video.

  set(AV1E_SET_ENABLE_CDEF, enableCDEF ? 1 : 0);
  set(AV1E_SET_ENABLE_RESTORATION, enableRestoration ? 1 : 0);

  // we are working for images.
  set(AV1E_SET_FORCE_VIDEO_MODE, 0);

  (void)AV1E_SET_ENABLE_OBMC; // is for video, motion prediction.
  // OBMC is "Overlapped Block Motion Compensation"
  // https://jmvalin.ca/papers/AV1_tools.pdf

  (void)AV1E_SET_DISABLE_TRELLIS_QUANT; // is for video(motion estimation).
  // https://en.wikipedia.org/wiki/Trellis_quantization

  if (useQM) {
    set(AV1E_SET_ENABLE_QM, 1);
    set(AV1E_SET_QM_MIN, qmMin);
    set(AV1E_SET_QM_MAX, qmMax);
    set(AV1E_SET_QM_Y, qmMinY);
    set(AV1E_SET_QM_U, qmMinU);
    set(AV1E_SET_QM_V, qmMinV);
  }

  //set(AV1E_SET_NUM_TG, (1u << static_cast<unsigned int>(tileRows)) + (1u << static_cast<unsigned int>(tileColumns)));

  (void)AV1E_SET_MTU; // is not needed to set, because AV1E_SET_NUM_TG is already set.
  set(AV1E_SET_ENABLE_RECT_PARTITIONS, enableRectPartition ? 1 : 0);
  set(AV1E_SET_ENABLE_AB_PARTITIONS, enableABPartition ? 1 : 0);
  set(AV1E_SET_ENABLE_1TO4_PARTITIONS, enable1to4Partition ? 1 : 0);
  set(AV1E_SET_MIN_PARTITION_SIZE, minPartitionSize);
  set(AV1E_SET_MAX_PARTITION_SIZE, maxPartitionSize);
  set(AV1E_SET_ENABLE_INTRA_EDGE_FILTER, enableIntraEdgeFilter ? 1 : 0);
  (void)AV1E_SET_ENABLE_ORDER_HINT; // is for video
  set(AV1E_SET_ENABLE_TX64, enableTX64 ? 1 : 0);
  set(AV1E_SET_ENABLE_FLIP_IDTX, enableFlipIDTX ? 1 : 0);
  // FIXME(ledyba-z): Please upgrade libaom
  //set(AV1E_SET_ENABLE_RECT_TX, enableRectTX ? 1 : 0);
  (void)AV1E_SET_ENABLE_DIST_WTD_COMP; // is for video
  (void)AV1E_SET_ENABLE_REF_FRAME_MVS; // is for video
  (void)AV1E_SET_ALLOW_REF_FRAME_MVS; // is for video
  set(AV1E_SET_ENABLE_DUAL_FILTER, 0);
  set(AV1E_SET_ENABLE_CHROMA_DELTAQ, enableChromaDeltaQ ? 1 : 0);
  (void)AV1E_SET_ENABLE_MASKED_COMP; // is for video
  (void)AV1E_SET_ENABLE_ONESIDED_COMP; // is for video
  (void)AV1E_SET_ENABLE_INTERINTRA_COMP; // is for video
  (void)AV1E_SET_ENABLE_SMOOTH_INTERINTRA; // is for video
  (void)AV1E_SET_ENABLE_DIFF_WTD_COMP; // is for video
  (void)AV1E_SET_ENABLE_INTERINTER_WEDGE; // is for video
  (void)AV1E_SET_ENABLE_GLOBAL_MOTION; // is for video
  set(AV1E_SET_ENABLE_GLOBAL_MOTION, 0);
  set(AV1E_SET_ENABLE_WARPED_MOTION, 0);
  (void)AV1E_SET_ALLOW_WARPED_MOTION; // is for video
  set(AV1E_SET_ENABLE_FILTER_INTRA, enableFilterIntra ? 1 : 0);
  set(AV1E_SET_ENABLE_SMOOTH_INTRA, enableSmoothIntra ? 1 : 0);
  set(AV1E_SET_ENABLE_PAETH_INTRA, enablePaethIntra ? 1 : 0);
  set(AV1E_SET_ENABLE_CFL_INTRA, enableChromaFromLuma ? 1 : 0);
  set(AV1E_SET_ENABLE_SUPERRES, enableSuperres ? 1 : 0);
  (void)AV1E_SET_ENABLE_OVERLAY; // is for video.
  set(AV1E_SET_ENABLE_PALETTE, enablePalette ? 1 : 0);
  set(AV1E_SET_ENABLE_INTRABC, enableIntraBC ? 1 : 0);
  set(AV1E_SET_DELTAQ_MODE, deltaQMode);
  set(AV1E_SET_DELTALF_MODE, enableDeltaLoopfilter ? 1 : 0);
  (void)AV1E_SET_SINGLE_TILE_DECODING; // is for video.
  (void)AV1E_ENABLE_MOTION_VECTOR_UNIT_TEST; // is for video.
  (void)AV1E_SET_TIMING_INFO_TYPE; // is for video.
  (void)AV1E_SET_FILM_GRAIN_TEST_VECTOR; // is for testing
  (void)AV1E_SET_FILM_GRAIN_TABLE; // can be supported, but it is mainly for video.
  (void)AV1E_SET_DENOISE_NOISE_LEVEL; // can be supported, but it is mainly for video.
  (void)AV1E_SET_DENOISE_BLOCK_SIZE; // can be supported, but it is mainly for video.
  set(AV1E_SET_REDUCED_TX_TYPE_SET, useReducedTXSet ? 1 : 0);
  set(AV1E_SET_INTRA_DCT_ONLY, useDCTOnly ? 1 : 0);
  set(AV1E_SET_INTRA_DEFAULT_TX_ONLY, useDefaultTXOnly ? 1 : 0);
  set(AV1E_SET_QUANT_B_ADAPT, enableAdaptiveQuantizationB ? 1 : 0);
  (void)AV1E_SET_GF_MAX_PYRAMID_HEIGHT; // is for video.
  (void)AV1E_SET_MAX_REFERENCE_FRAMES; // is for video.
  (void)AV1E_SET_REDUCED_REFERENCE_SET; // is for video.
  (void)AV1E_SET_COEFF_COST_UPD_FREQ; // may be for video, because it mentions tile decoding.
  (void)AV1E_SET_MODE_COST_UPD_FREQ; // may be for video, because it mentions tile decoding.
  (void)AV1E_SET_MV_COST_UPD_FREQ; // may be for video, because it mentions tile decoding.
  (void)AV1E_SET_TIER_MASK; // for video, because still picture always has 1 control point.
  (void)AV1E_SET_MIN_CR; // is for video. My GDB says that.
  (void)AV1E_SET_SVC_LAYER_ID; // is for video.
  (void)AV1E_SET_SVC_PARAMS; // is for video.
  (void)AV1E_SET_SVC_REF_FRAME_CONFIG; // is for video.
  /*if (!vmafModelPath.empty()) {
    set(AV1E_SET_VMAF_MODEL_PATH, vmafModelPath.c_str());
  }*/
  (void)AV1E_ENABLE_EXT_TILE_DEBUG;// is for debugging.
  (void)AV1E_ENABLE_SB_MULTIPASS_UNIT_TEST;// is for unit test.
  (void)AV1E_SET_GF_MIN_PYRAMID_HEIGHT; // is for video.

  // FIXME(ledyba-z): Please upgrade libaom
  //(void)AV1E_SET_VBR_CORPUS_COMPLEXITY_LAP; // is for video.
  //(void)AV1E_GET_BASELINE_GF_INTERVAL; // is for video.

#undef set
}
// Only positive speeds, range for real-time coding currently is: 6 - 8.
// Lower means slower/better quality, higher means fastest/lower quality.
static int GetCpuSpeed(int width, int height, int number_of_cores) {
  // For smaller resolutions, use lower speed setting (get some coding gain at
  // the cost of increased encoding complexity).
  if (number_of_cores > 4 && width * height < 320 * 180)
    return 6;
  else if (width * height >= 1280 * 720)
    return 9;
  else if (width * height >= 640 * 360)
    return 8;
  else
    return 7;
}
static aom_superblock_size_t GetSuperblockSize(int width, int height, int threads) {
  int resolution = width * height;
  if (threads >= 4 && resolution >= 960 * 540 && resolution < 1920 * 1080)
    return AOM_SUPERBLOCK_SIZE_64X64;
  else
    return AOM_SUPERBLOCK_SIZE_DYNAMIC;
}
static int NumberOfThreads(int width,
  int height,
  int number_of_cores) {
  // Keep the number of encoder threads equal to the possible number of
  // column/row tiles, which is (1, 2, 4, 8). See comments below for
  // AV1E_SET_TILE_COLUMNS/ROWS.
  if (width * height >= 640 * 360 && number_of_cores > 4) {
    return 4;
  }
  else if (width * height >= 320 * 180 && number_of_cores > 2) {
    return 2;
  }
  else {
    // Use 2 threads for low res on ARM.
#if defined(WEBRTC_ARCH_ARM) || defined(WEBRTC_ARCH_ARM64) || 
    defined(WEBRTC_ANDROID)
    if (width * height >= 320 * 180 && number_of_cores > 2) {
      return 2;
    }
#endif
    // 1 thread less than VGA.
    return 1;
  }
}
static void av1enc_parameter_set(struct xav_encoder_t* av1, const struct av1_parameter_t* param)
{
  /// Color Format correction.
  switch (param->format) {
  //case PICTURE_RGBA:
  //  //PLOG_WARNING("Color Format RGBA not supported, using BGRA instead.");
  //  av1->imageFormat = AOM_IMG_FMT_ARGB_LE;
  //  break;
  ////case VIDEO_FORMAT_BGRX:
  ////  //PLOG_WARNING("Color Format BGRX not supported, using BGRA instead.");
  ////  av1->imageFormat = AOM_IMG_FMT_ARGB_LE;
  ////  break;
  //case PICTURE_BGRA:
  //  av1->imageFormat = AOM_IMG_FMT_ARGB_LE;
  //  break;
  //case VIDEO_FORMAT_YVYU:
  //  av1->imageFormat = AOM_IMG_FMT_YVYU;
  //  break;
  //case VIDEO_FORMAT_YUY2:
  //  av1->imageFormat = AOM_IMG_FMT_YUY2;
  //  break;
  //case VIDEO_FORMAT_UYVY:
  //  av1->imageFormat = AOM_IMG_FMT_UYVY;
  //  break;
  //case VIDEO_FORMAT_Y800:
  //  //PLOG_WARNING("Color Format Y800 not supported, using I420 instead.");
  //  m_imageFormat = AOM_IMG_FMT_I420;
  //  break;
  case PICTURE_NV12:
    //PLOG_WARNING("Color Format NV12 not supported, using I420 instead.");
    av1->imageFormat = AOM_IMG_FMT_I420;
    break;
  case PICTURE_YUV420:
    av1->imageFormat = AOM_IMG_FMT_I420;
    break;
  case PICTURE_YUV444:
    av1->imageFormat = AOM_IMG_FMT_I444;
    break;
  }
  const struct aom_codec_iface* iface = aom_codec_av1_cx();
  aom_codec_err_t ret =
    aom_codec_enc_config_default(iface, &av1->configuration, AOM_USAGE_GOOD_QUALITY);
  if (ret != AOM_CODEC_OK) {
  
    return ;
  }
  av1->configuration.g_timebase.den = param->den;
  av1->configuration.g_timebase.num = param->num;
  av1->configuration.g_w = param->width;
  av1->configuration.g_h = param->height;
  av1->configuration.g_threads =
    NumberOfThreads(av1->configuration.g_w, av1->configuration.g_h, 4);
  av1->configuration.g_input_bit_depth = AOM_BITS_8;
  av1->configuration.g_bit_depth = AOM_BITS_8;

  av1->configuration.rc_target_bitrate = param->bitrate;//maxBitrate = 1000; kilobits/sec.
  av1->configuration.g_usage = AOM_USAGE_REALTIME;


  //av1->maxencodetime = ((double)param->den/ (double)param->num) * 1000000;

  
  //av1->configuration.rc_min_quantizer = 2;
  //av1->configuration.rc_max_quantizer = 52;
  av1->configuration.rc_undershoot_pct = 50;
  av1->configuration.rc_overshoot_pct = 50;
  av1->configuration.rc_buf_initial_sz = 600;
  av1->configuration.rc_buf_optimal_sz = 600;
  av1->configuration.rc_buf_sz = 1000;
  //av1->configuration.rc_resize_mode = 0;  // Set to RESIZE_DYNAMIC for dynamic resize.
  
  //av1->configuration.kf_mode = AOM_KF_AUTO;
  av1->configuration.g_error_resilient = 0;
    // Low-latency settings.
  av1->configuration.rc_end_usage = AOM_CBR; // Constant Bit Rate (CBR) mode
  av1->configuration.g_pass = AOM_RC_ONE_PASS;// One-pass rate control
  av1->configuration.g_lag_in_frames = 0; // No look ahead when lag equals 0.

  // FIXME(ledyba-z): Encoder produces wrong images when g_input_bit_depth != g_bit_depth. Bug?
  //av1->configuration.g_input_bit_depth = av1->configuration.g_bit_depth;
  // FIXME(ledyba-z): If kf_max_dist = 1, it crashes. Bug?
  // > A value of 0 implies all frames will be keyframes.
  // However, when it is set to 0, assertion always fails:
  // cavif/external/libaom/av1/encoder/gop_structure.c:92:
  // construct_multi_layer_gf_structure: Assertion `gf_interval >= 1' failed.
  //av1->configuration.kf_max_dist = 1;
  //av1->configuration.g_limit = 1;
  // Create frame buffer.
  //av1->configuration.g_threads = 10;
  if (!aom_img_alloc(&av1->image, av1->imageFormat, param->width, param->height, 1)) {
    //throw std::runtime_error("Failed to create frame buffer.");
    printf("Failed to create frame buffer.n");
  }
  else {
    /*switch (param->range) {
    case VIDEO_RANGE_PARTIAL:
      av1->image.range = aom_color_range_t::AOM_CR_STUDIO_RANGE;
      break;
    default:
      av1->image.range = aom_color_range_t::AOM_CR_FULL_RANGE;
      break;
    }
    switch (voi->colorspace) {
    case VIDEO_CS_601:
      av1->image.cs = aom_color_space_t::AOM_CS_BT_601;
      break;
    case VIDEO_CS_DEFAULT:
    case VIDEO_CS_709:
      av1->image.cs = aom_color_space_t::AOM_CS_BT_709;
      break;
    }*/
  }

  aom_codec_flags_t flags = 0;
  if (av1->configuration.g_bit_depth > 8) {
    flags = AOM_CODEC_USE_HIGHBITDEPTH;
  }


  // Initialize
  aom_codec_err_t res = aom_codec_enc_init(&av1->codec, iface, &av1->configuration, flags);
  if (res != AOM_CODEC_OK) {
    //std::vector<char> buf(1024);
    //sprintf(buf.data(), "Failed to initialize encoder, code %d.", res);
    printf("Failed to initialize encoder, code  %d.n", res);
    
  }
  //modify(&av1->codec);
    // Set control parameters
  ret = aom_codec_control(
    &av1->codec, AOME_SET_CPUUSED,
    GetCpuSpeed(av1->configuration.g_w, av1->configuration.g_h, 2));
  if (ret != AOM_CODEC_OK) {
  /*  RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret
      << " on control AV1E_SET_CPUUSED.";
    return WEBRTC_VIDEO_CODEC_ERROR;*/
  }
  ret = aom_codec_control(&av1->codec, AV1E_SET_ENABLE_CDEF, 1);
  if (ret != AOM_CODEC_OK) {
  /*  RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret
      << " on control AV1E_SET_ENABLE_CDEF.";
    return WEBRTC_VIDEO_CODEC_ERROR;*/
  }
  ret = aom_codec_control(&av1->codec, AV1E_SET_ENABLE_TPL_MODEL, 0);
  if (ret != AOM_CODEC_OK) {
    /*RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret
      << " on control AV1E_SET_ENABLE_TPL_MODEL.";
    return WEBRTC_VIDEO_CODEC_ERROR;*/
  }
  ret = aom_codec_control(&av1->codec, AV1E_SET_DELTAQ_MODE, 0);
  if (ret != AOM_CODEC_OK) {
  /*  RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret
      << " on control AV1E_SET_DELTAQ_MODE.";
    return WEBRTC_VIDEO_CODEC_ERROR;*/
  }
  ret = aom_codec_control(&av1->codec, AV1E_SET_ENABLE_ORDER_HINT, 0);
  if (ret != AOM_CODEC_OK) {
    /*RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret
      << " on control AV1E_SET_ENABLE_ORDER_HINT.";
    return WEBRTC_VIDEO_CODEC_ERROR;*/
  }
  ret = aom_codec_control(&av1->codec, AV1E_SET_AQ_MODE, 3);
  if (ret != AOM_CODEC_OK) {
    /*RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret
      << " on control AV1E_SET_AQ_MODE.";
    return WEBRTC_VIDEO_CODEC_ERROR;*/
  }
  //if (SvcEnabled()) {
  //  ret = aom_codec_control(&av1->codec, AV1E_SET_SVC_PARAMS, &*svc_params_);
  //  if (ret != AOM_CODEC_OK) {
  //  /*  RTC_LOG(LS_WARNING) << "LibaomAV1Encoder::EncodeInit returned " << ret
  //      << " on control AV1E_SET_SVC_PARAMS.";
  //    return false;*/
  //  }
  //}

  ret = aom_codec_control(&av1->codec, AOME_SET_MAX_INTRA_BITRATE_PCT, 300);
  if (ret != AOM_CODEC_OK) {
    /*RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret
      << " on control AV1E_SET_MAX_INTRA_BITRATE_PCT.";
    return WEBRTC_VIDEO_CODEC_ERROR;*/
  }
  ret = aom_codec_control(&av1->codec, AV1E_SET_COEFF_COST_UPD_FREQ, 3);
  if (ret != AOM_CODEC_OK) {
    /*RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret
      << " on control AV1E_SET_COEFF_COST_UPD_FREQ.";
    return WEBRTC_VIDEO_CODEC_ERROR;*/
  }
  ret = aom_codec_control(&av1->codec, AV1E_SET_MODE_COST_UPD_FREQ, 3);
  if (ret != AOM_CODEC_OK) {
    /*RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret
      << " on control AV1E_SET_MODE_COST_UPD_FREQ.";
    return WEBRTC_VIDEO_CODEC_ERROR;*/
  }
  ret = aom_codec_control(&av1->codec, AV1E_SET_MV_COST_UPD_FREQ, 3);
  if (ret != AOM_CODEC_OK) {
    /*RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret
      << " on control AV1E_SET_MV_COST_UPD_FREQ.";
    return WEBRTC_VIDEO_CODEC_ERROR;*/
  }

  if (av1->configuration.g_threads == 4 && av1->configuration.g_w == 640 &&
    (av1->configuration.g_h == 360 || av1->configuration.g_h == 480)) {
    ret = aom_codec_control(&av1->codec, AV1E_SET_TILE_ROWS,
      (log2(av1->configuration.g_threads)));
    if (ret != AOM_CODEC_OK) {
      /*RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret
        << " on control AV1E_SET_TILE_ROWS.";
      return WEBRTC_VIDEO_CODEC_ERROR;*/
    }
  }
  else {
    ret = aom_codec_control(&av1->codec, AV1E_SET_TILE_COLUMNS,
    (log2(av1->configuration.g_threads)));
    if (ret != AOM_CODEC_OK) {
  /*    RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret
        << " on control AV1E_SET_TILE_COLUMNS.";
      return WEBRTC_VIDEO_CODEC_ERROR;*/
    }
  }

  ret = aom_codec_control(&av1->codec, AV1E_SET_ROW_MT, 1);
  if (ret != AOM_CODEC_OK) {
  /*  RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret
      << " on control AV1E_SET_ROW_MT.";
    return WEBRTC_VIDEO_CODEC_ERROR;*/
  }

  ret = aom_codec_control(&av1->codec, AV1E_SET_ENABLE_OBMC, 0);
  if (ret != AOM_CODEC_OK) {
    /*RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret
      << " on control AV1E_SET_ENABLE_OBMC.";
    return WEBRTC_VIDEO_CODEC_ERROR;*/
  }

  ret = aom_codec_control(&av1->codec, AV1E_SET_NOISE_SENSITIVITY, 0);
  if (ret != AOM_CODEC_OK) {
    /*RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret
      << " on control AV1E_SET_NOISE_SENSITIVITY.";
    return WEBRTC_VIDEO_CODEC_ERROR;*/
  }

  ret = aom_codec_control(&av1->codec, AV1E_SET_ENABLE_WARPED_MOTION, 0);
  if (ret != AOM_CODEC_OK) {
  /*  RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret
      << " on control AV1E_SET_ENABLE_WARPED_MOTION.";
    return WEBRTC_VIDEO_CODEC_ERROR;*/
  }

  ret = aom_codec_control(&av1->codec, AV1E_SET_ENABLE_GLOBAL_MOTION, 0);
  if (ret != AOM_CODEC_OK) {
    /*RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret
      << " on control AV1E_SET_ENABLE_GLOBAL_MOTION.";
    return WEBRTC_VIDEO_CODEC_ERROR;*/
  }

  ret = aom_codec_control(&av1->codec, AV1E_SET_ENABLE_REF_FRAME_MVS, 0);
  if (ret != AOM_CODEC_OK) {
    /*RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret
      << " on control AV1E_SET_ENABLE_REF_FRAME_MVS.";
    return WEBRTC_VIDEO_CODEC_ERROR;*/
  }

  ret =
    aom_codec_control(&av1->codec, AV1E_SET_SUPERBLOCK_SIZE,
      GetSuperblockSize(av1->configuration.g_w, av1->configuration.g_h, av1->configuration.g_threads));
  if (ret != AOM_CODEC_OK) {
    /*RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret
      << " on control AV1E_SET_SUPERBLOCK_SIZE.";
    return WEBRTC_VIDEO_CODEC_ERROR;*/
  }

  ret = aom_codec_control(&av1->codec, AV1E_SET_ENABLE_CFL_INTRA, 0);
  if (ret != AOM_CODEC_OK) {
    /*RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret
      << " on control AV1E_SET_ENABLE_CFL_INTRA.";
    return WEBRTC_VIDEO_CODEC_ERROR;*/
  }

  ret = aom_codec_control(&av1->codec, AV1E_SET_ENABLE_SMOOTH_INTRA, 0);
  if (ret != AOM_CODEC_OK) {
  /*  RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret
      << " on control AV1E_SET_ENABLE_SMOOTH_INTRA.";
    return WEBRTC_VIDEO_CODEC_ERROR;*/
  }

  ret = aom_codec_control(&av1->codec, AV1E_SET_ENABLE_ANGLE_DELTA, 0);
  if (ret != AOM_CODEC_OK) {
  /*  RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret
      << " on control AV1E_SET_ENABLE_ANGLE_DELTA.";
    return WEBRTC_VIDEO_CODEC_ERROR;*/
  }

  ret = aom_codec_control(&av1->codec, AV1E_SET_ENABLE_FILTER_INTRA, 0);
  if (ret != AOM_CODEC_OK) {
  /*  RTC_LOG(LS_WARNING) << "LibaomAv1Encoder::EncodeInit returned " << ret
      << " on control AV1E_SET_ENABLE_FILTER_INTRA.";*/
    //return WEBRTC_VIDEO_CODEC_ERROR;
  }

  ret = aom_codec_control(&av1->codec, AV1E_SET_INTRA_DEFAULT_TX_ONLY, 1);
  if (ret != AOM_CODEC_OK) {
  /*  RTC_LOG(LS_WARNING)
      << "LibaomAv1Encoder::EncodeInit returned " << ret
      << " on control AOM_CTRL_AV1E_SET_INTRA_DEFAULT_TX_ONLY.";*/
    //return WEBRTC_VIDEO_CODEC_ERROR;
  }

}

static void* av1enc_create(const struct av1_parameter_t* param)
{
  struct xav_encoder_t* p;
  p = (struct xav_encoder_t*)malloc(sizeof(struct xav_encoder_t));
  if (NULL == p)
    return NULL;
  av1enc_parameter_set(p, param);
  return p;
}

static void av1enc_destroy(void* av1)
{
  struct xav_encoder_t* p;
  p = (struct xav_encoder_t*)av1;
  aom_codec_destroy(&p->codec);
}

static int av1enc_input(void* av1, const struct avframe_t* pic)
{
  struct xav_encoder_t* p;
  p = (struct xav_encoder_t*)av1;
  //if (p->imageFormat == AOM_IMG_FMT_ARGB_LE) {
  //  //std::memcpy(m_image.planes[AOM_PLANE_PACKED], frame->data[0], frame->linesize[0] * m_image.h);
  //}
   if (p->imageFormat == AOM_IMG_FMT_I444) {
     p->image.planes[AOM_PLANE_Y], pic->data[0], pic->linesize[0] * p->image.h;
     p->image.planes[AOM_PLANE_U], pic->data[1], pic->linesize[1] * p->image.h;
     p->image.planes[AOM_PLANE_V], pic->data[2], pic->linesize[2] * p->image.h;
  }
  else if (p->imageFormat == AOM_IMG_FMT_I420) {
    // p->image.planes[AOM_PLANE_Y], pic->data[0], pic->linesize[0] * p->image.h;
    // p->image.planes[AOM_PLANE_U], pic->data[1], pic->linesize[1] * p->image.h / 2;
    // p->image.planes[AOM_PLANE_V], pic->data[2], pic->linesize[2] * p->image.h / 2;

    /* memcpy(p->image.planes[AOM_PLANE_Y], pic->data[0], pic->linesize[0] * p->image.h);
     memcpy(p->image.planes[AOM_PLANE_U], pic->data[1], pic->linesize[1] * p->image.h / 2);
     memcpy(p->image.planes[AOM_PLANE_V], pic->data[2], pic->linesize[2] * p->image.h / 2);*/

     p->image.planes[AOM_PLANE_Y] = pic->data[0];
     p->image.planes[AOM_PLANE_U] = pic->data[1];
     p->image.planes[AOM_PLANE_V] = pic->data[2];
     p->image.stride[AOM_PLANE_Y] = pic->linesize[0];
     p->image.stride[AOM_PLANE_U] = pic->linesize[1];
     p->image.stride[AOM_PLANE_V] = pic->linesize[2];

    


  }

  int flags = 0;
  if (pic->flags)
  flags |= AOM_EFLAG_FORCE_KF;
  aom_codec_err_t res = aom_codec_encode(&p->codec, &p->image, pic->dts, 1/*p->maxencodetime*/, flags);
   if (res != AOM_CODEC_OK) {
    
     const char* detail = aom_codec_error_detail(&p->codec);
     fprintf(stderr, " %sn",  aom_codec_error(&p->codec));
     if (detail) printf("    %sn", detail);

     return 0;
   }
  return 1;
}

static int av1enc_getpacket(void* av1, struct avpacket_t* packet)
{
  struct xav_encoder_t* p;
  p = (struct xav_encoder_t*)av1;
  const struct aom_codec_cx_pkt* pkt;
  const void* iter = NULL;
  /* consume all available output from the encoder before returning. buffers
 * are only good through the next aom_codec call */
  while ((pkt = aom_codec_get_cx_data(&p->codec, &iter))) {
    //printf("00000n");
    switch (pkt->kind) {
    case AOM_CODEC_CX_FRAME_PKT:
    {packet->pts = pkt->data.frame.pts;
    packet->size = pkt->data.frame.sz;
    packet->flags = pkt->data.frame.flags & AOM_FRAME_IS_KEY;
    packet->data = (uint8_t*)pkt->data.frame.buf;
    packet->dts = packet->pts - pkt->data.frame.duration;

    /*static FILE* g_yuvfp = NULL;
    if (!g_yuvfp)
    {
      g_yuvfp = fopen("D:/5688.obu", "wb");
    }
    fwrite(packet->data, 1, packet->size, g_yuvfp);
    fflush(g_yuvfp);*/
    
    }break;
    case AOM_CODEC_STATS_PKT:
    {
      printf("AOM_CODEC_STATS_PKTn");
    }break;
    }
  }
  /*aom_codec_iter_t iter = NULL;
  for (const aom_codec_cx_pkt_t* pkt = aom_codec_get_cx_data(&p->codec, &iter); pkt != NULL; pkt = aom_codec_get_cx_data(&p->codec, &iter)) {
    printf("55555n");
    if (pkt->kind == AOM_CODEC_CX_FRAME_PKT) {
      packet->pts = pkt->data.frame.pts;
      packet->size = pkt->data.frame.sz;
      packet->flags = pkt->data.frame.flags & AOM_FRAME_IS_KEY;
      packet->data = (uint8_t*)pkt->data.frame.buf;
      packet->dts = packet->pts - pkt->data.frame.duration;

      static FILE* g_yuvfp = NULL;
      if (!g_yuvfp)
      {
        g_yuvfp = fopen("D:/5688.obu", "wb");
      }
      fwrite(packet->data, 1, packet->size, g_yuvfp);
      fflush(g_yuvfp);

      return 1;
    } // ToDo: determine live two-pass encoding, technically possible.
  }*/
  return 0;
}

struct av1_encoder_t* hav1_encoder(void)
{
  static struct av1_encoder_t s_encoder = {
    av1enc_create,
    av1enc_destroy,
    av1enc_input,
    av1enc_getpacket,
  };
  return &s_encoder;
}
#endif

Offer SDP


v=0
o=- 9162866787994700278 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0 1
a=extmap-allow-mixed
a=msid-semantic: WMS Dt5YcqBdN5php8AwHouypKamyLJT9Fezj4ic
m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:HV8K
a=ice-pwd:drEV18nSyHA7EiWr1D9j37LN
a=ice-options:trickle
a=fingerprint:sha-256 D1:3E:D0:4E:5F:91:AA:08:33:DE:33:C0:3D:82:D4:C9:85:9B:70:78:F4:B8:71:5F:51:E0:8F:E8:0D:EC:54:5B
a=setup:actpass
a=mid:0
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=sendrecv
a=msid:Dt5YcqBdN5php8AwHouypKamyLJT9Fezj4ic 6449b513-ce07-4e2f-a64d-d507013d0d1c
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:112 telephone-event/32000
a=rtpmap:113 telephone-event/16000
a=rtpmap:126 telephone-event/8000
a=ssrc:1966315384 cname:p1AjwDY1akYv5Xyl
a=ssrc:1966315384 msid:Dt5YcqBdN5php8AwHouypKamyLJT9Fezj4ic 6449b513-ce07-4e2f-a64d-d507013d0d1c
a=ssrc:1966315384 mslabel:Dt5YcqBdN5php8AwHouypKamyLJT9Fezj4ic
a=ssrc:1966315384 label:6449b513-ce07-4e2f-a64d-d507013d0d1c
m=video 9 UDP/TLS/RTP/SAVPF 35
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:HV8K
a=ice-pwd:drEV18nSyHA7EiWr1D9j37LN
a=ice-options:trickle
a=fingerprint:sha-256 D1:3E:D0:4E:5F:91:AA:08:33:DE:33:C0:3D:82:D4:C9:85:9B:70:78:F4:B8:71:5F:51:E0:8F:E8:0D:EC:54:5B
a=setup:actpass
a=mid:1
a=extmap:14 urn:ietf:params:rtp-hdrext:toffset
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:13 urn:3gpp:video-orientation
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:12 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=extmap:11 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type
a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing
a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=sendrecv
a=msid:Dt5YcqBdN5php8AwHouypKamyLJT9Fezj4ic a41f6233-d0de-4bf0-9479-ae9cd6a8b6d6
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:35 AV1X/90000
a=rtcp-fb:35 goog-remb
a=rtcp-fb:35 transport-cc
a=rtcp-fb:35 ccm fir
a=rtcp-fb:35 nack
a=rtcp-fb:35 nack pli
a=ssrc:1975300151 cname:p1AjwDY1akYv5Xyl
a=ssrc:1975300151 msid:Dt5YcqBdN5php8AwHouypKamyLJT9Fezj4ic a41f6233-d0de-4bf0-9479-ae9cd6a8b6d6
a=ssrc:1975300151 mslabel:Dt5YcqBdN5php8AwHouypKamyLJT9Fezj4ic
a=ssrc:1975300151 label:a41f6233-d0de-4bf0-9479-ae9cd6a8b6d6
Answer SDP
v=0
o=- 4364282017263967299 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0 1
a=extmap-allow-mixed
a=msid-semantic: WMS LEIFoUMg2FIy2rR4gIIOJQ1UZ6Rk9IWHLrZn
m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:pENq
a=ice-pwd:P/6Yb4ThwQQM75aUlinnDysZ
a=ice-options:trickle
a=fingerprint:sha-256 A0:BB:90:F9:2F:3C:43:91:6D:7F:4D:D2:51:C1:75:6D:64:1F:F2:E5:58:B7:6F:E0:05:31:FA:5E:85:2E:59:71
a=setup:active
a=mid:0
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=sendrecv
a=msid:LEIFoUMg2FIy2rR4gIIOJQ1UZ6Rk9IWHLrZn 1ecdef46-ec10-412b-8d75-17b311dc4e39
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:112 telephone-event/32000
a=rtpmap:113 telephone-event/16000
a=rtpmap:126 telephone-event/8000
a=ssrc:2979558157 cname:gQ6GVcZSPVJEx0l1
m=video 9 UDP/TLS/RTP/SAVPF 35
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:pENq
a=ice-pwd:P/6Yb4ThwQQM75aUlinnDysZ
a=ice-options:trickle
a=fingerprint:sha-256 A0:BB:90:F9:2F:3C:43:91:6D:7F:4D:D2:51:C1:75:6D:64:1F:F2:E5:58:B7:6F:E0:05:31:FA:5E:85:2E:59:71
a=setup:active
a=mid:1
a=extmap:14 urn:ietf:params:rtp-hdrext:toffset
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:13 urn:3gpp:video-orientation
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:12 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=extmap:11 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type
a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing
a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=sendrecv
a=msid:LEIFoUMg2FIy2rR4gIIOJQ1UZ6Rk9IWHLrZn 7389e855-b866-4886-ac61-f5782cb6ed77
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:35 AV1X/90000
a=rtcp-fb:35 goog-remb
a=rtcp-fb:35 transport-cc
a=rtcp-fb:35 ccm fir
a=rtcp-fb:35 nack
a=rtcp-fb:35 nack pli
a=ssrc:722599194 cname:gQ6GVcZSPVJEx0l1

彩蛋:

图片

作者:Aliveyun

版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。

(0)

相关推荐

发表回复

登录后才能评论