avformat/movenc: add support for LCEVC track muxing
Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
@@ -3,6 +3,7 @@ releases are sorted from youngest to oldest.
|
||||
|
||||
version <next>:
|
||||
- Extend AMF Color Converter (vf_vpp_amf) HDR capabilities
|
||||
- LCEVC track muxing support in MP4 muxer
|
||||
|
||||
|
||||
version 8.1:
|
||||
|
||||
@@ -1135,6 +1135,7 @@ STLIBOBJS-$(CONFIG_IMAGE_JPEGXL_PIPE_DEMUXER) += jpegxl_parse.o
|
||||
STLIBOBJS-$(CONFIG_JPEGXL_ANIM_DEMUXER) += jpegxl_parse.o
|
||||
STLIBOBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio_sample_rates.o
|
||||
STLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o
|
||||
STLIBOBJS-$(CONFIG_MOV_MUXER) += h2645_parse.o lcevctab.o
|
||||
STLIBOBJS-$(CONFIG_MXF_MUXER) += golomb.o
|
||||
STLIBOBJS-$(CONFIG_MP3_MUXER) += mpegaudiotabs.o
|
||||
STLIBOBJS-$(CONFIG_NUT_MUXER) += mpegaudiotabs.o
|
||||
|
||||
@@ -389,7 +389,8 @@ OBJS-$(CONFIG_MOV_DEMUXER) += mov.o mov_chan.o mov_esds.o \
|
||||
OBJS-$(CONFIG_MOV_MUXER) += movenc.o \
|
||||
movenchint.o mov_chan.o rtp.o \
|
||||
movenccenc.o movenc_ttml.o rawutils.o \
|
||||
apv.o dovi_isom.o evc.o cbs.o cbs_av1.o cbs_apv.o
|
||||
apv.o dovi_isom.o evc.o cbs.o cbs_av1.o cbs_apv.o \
|
||||
lcevc.o
|
||||
OBJS-$(CONFIG_MP2_MUXER) += rawenc.o
|
||||
OBJS-$(CONFIG_MP3_DEMUXER) += mp3dec.o replaygain.o
|
||||
OBJS-$(CONFIG_MP3_MUXER) += mp3enc.o rawenc.o id3v2enc.o
|
||||
@@ -751,6 +752,7 @@ SHLIBOBJS-$(CONFIG_JPEGXL_ANIM_DEMUXER) += jpegxl_parse.o
|
||||
SHLIBOBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio_sample_rates.o
|
||||
SHLIBOBJS-$(CONFIG_MATROSKA_MUXER) += opus_frame_duration_tab.o
|
||||
SHLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o
|
||||
SHLIBOBJS-$(CONFIG_MOV_MUXER) += h2645_parse.o lcevctab.o
|
||||
SHLIBOBJS-$(CONFIG_MP3_MUXER) += mpegaudiotabs.o
|
||||
SHLIBOBJS-$(CONFIG_MXF_MUXER) += golomb_tab.o \
|
||||
rangecoder_dec.o
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "libavcodec/h2645_parse.c"
|
||||
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* LCEVC helper functions for muxers
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "libavutil/error.h"
|
||||
#include "libavutil/intreadwrite.h"
|
||||
#include "libavutil/mem.h"
|
||||
#include "libavcodec/bytestream.h"
|
||||
#include "libavcodec/h2645_parse.h"
|
||||
#include "libavcodec/lcevc.h"
|
||||
#include "libavcodec/lcevctab.h"
|
||||
#include "libavcodec/lcevc_parse.h"
|
||||
#include "avio.h"
|
||||
#include "avio_internal.h"
|
||||
#include "lcevc.h"
|
||||
|
||||
typedef struct LCEVCDecoderConfigurationRecord {
|
||||
uint8_t profile_idc;
|
||||
uint8_t level_idc;
|
||||
uint8_t chroma_format_idc;
|
||||
uint8_t bit_depth_luma_minus8;
|
||||
uint8_t bit_depth_chroma_minus8;
|
||||
uint32_t pic_width_in_luma_samples;
|
||||
uint32_t pic_height_in_luma_samples;
|
||||
} LCEVCDecoderConfigurationRecord;
|
||||
|
||||
/**
|
||||
* Rewrite the NALu stripping the unneeded blocks.
|
||||
* Given that length fields coded inside the NALu are not aware of any emulation_3bytes
|
||||
* present in the bitstream, we need to keep track of the raw buffer as we navigate
|
||||
* the stripped buffer in order to write proper NALu sizes.
|
||||
*/
|
||||
static int write_nalu(LCEVCDecoderConfigurationRecord *lvcc, AVIOContext *pb,
|
||||
const H2645NAL *nal)
|
||||
{
|
||||
GetByteContext gbc, raw_gbc;
|
||||
int64_t start = avio_tell(pb), end;
|
||||
int sc = 0, gc = 0;
|
||||
int skipped_byte_pos = 0, nalu_length = 3;
|
||||
|
||||
bytestream2_init(&gbc, nal->data, nal->size);
|
||||
bytestream2_init(&raw_gbc, nal->raw_data, nal->raw_size);
|
||||
avio_wb16(pb, 0); // size placeholder
|
||||
avio_wb16(pb, bytestream2_get_be16(&gbc)); // nal_unit_header
|
||||
bytestream2_skip(&raw_gbc, 2);
|
||||
|
||||
while (bytestream2_get_bytes_left(&gbc) > 1 && (!sc || !gc)) {
|
||||
GetBitContext gb;
|
||||
uint64_t payload_size;
|
||||
int payload_size_type, payload_type;
|
||||
int block_size, raw_block_size, block_end;
|
||||
|
||||
init_get_bits8(&gb, gbc.buffer, bytestream2_get_bytes_left(&gbc));
|
||||
|
||||
payload_size_type = get_bits(&gb, 3);
|
||||
payload_type = get_bits(&gb, 5);
|
||||
payload_size = payload_size_type;
|
||||
if (payload_size_type == 6)
|
||||
return AVERROR_PATCHWELCOME;
|
||||
if (payload_size_type == 7)
|
||||
payload_size = get_mb(&gb);
|
||||
|
||||
if (payload_size > INT_MAX - (get_bits_count(&gb) >> 3))
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
block_size = raw_block_size = payload_size + (get_bits_count(&gb) >> 3);
|
||||
if (block_size >= bytestream2_get_bytes_left(&gbc))
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
block_end = bytestream2_tell(&gbc) + block_size;
|
||||
// Take into account removed emulation 3bytes, as payload_size in
|
||||
// the bitstream is not aware of them.
|
||||
for (; skipped_byte_pos < nal->skipped_bytes; skipped_byte_pos++) {
|
||||
if (nal->skipped_bytes_pos[skipped_byte_pos] >= block_end)
|
||||
break;
|
||||
raw_block_size++;
|
||||
}
|
||||
|
||||
switch (payload_type) {
|
||||
case 0:
|
||||
if (sc)
|
||||
break;
|
||||
|
||||
lvcc->profile_idc = get_bits(&gb, 4);
|
||||
lvcc->level_idc = get_bits(&gb, 4);
|
||||
|
||||
avio_write(pb, raw_gbc.buffer, raw_block_size);
|
||||
nalu_length += raw_block_size;
|
||||
sc = 1;
|
||||
break;
|
||||
case 1: {
|
||||
int resolution_type, bit_depth;
|
||||
int processed_planes_type_flag;
|
||||
|
||||
if (gc)
|
||||
break;
|
||||
|
||||
processed_planes_type_flag = get_bits1(&gb);
|
||||
resolution_type = get_bits(&gb, 6);
|
||||
|
||||
skip_bits1(&gb);
|
||||
lvcc->chroma_format_idc = get_bits(&gb, 2);
|
||||
|
||||
skip_bits(&gb, 2);
|
||||
bit_depth = get_bits(&gb, 2) * 2; // enhancement_depth_type
|
||||
lvcc->bit_depth_luma_minus8 = bit_depth;
|
||||
lvcc->bit_depth_chroma_minus8 = bit_depth;
|
||||
|
||||
if (resolution_type < 63) {
|
||||
lvcc->pic_width_in_luma_samples = ff_lcevc_resolution_type[resolution_type].width;
|
||||
lvcc->pic_height_in_luma_samples = ff_lcevc_resolution_type[resolution_type].height;
|
||||
} else {
|
||||
int upsample_type, tile_dimensions_type;
|
||||
int temporal_step_width_modifier_signalled_flag, level1_filtering_signalled_flag;
|
||||
// Skip syntax elements until we get to the custom dimension ones
|
||||
temporal_step_width_modifier_signalled_flag = get_bits1(&gb);
|
||||
skip_bits(&gb, 3);
|
||||
upsample_type = get_bits(&gb, 3);
|
||||
level1_filtering_signalled_flag = get_bits1(&gb);
|
||||
skip_bits(&gb, 4);
|
||||
tile_dimensions_type = get_bits(&gb, 2);
|
||||
skip_bits(&gb, 4);
|
||||
if (processed_planes_type_flag)
|
||||
skip_bits(&gb, 4);
|
||||
if (temporal_step_width_modifier_signalled_flag)
|
||||
skip_bits(&gb, 8);
|
||||
if (upsample_type)
|
||||
skip_bits_long(&gb, 64);
|
||||
if (level1_filtering_signalled_flag)
|
||||
skip_bits(&gb, 8);
|
||||
if (tile_dimensions_type) {
|
||||
if (tile_dimensions_type == 3)
|
||||
skip_bits_long(&gb, 32);
|
||||
skip_bits(&gb, 8);
|
||||
}
|
||||
|
||||
lvcc->pic_width_in_luma_samples = get_bits(&gb, 16);
|
||||
lvcc->pic_height_in_luma_samples = get_bits(&gb, 16);
|
||||
}
|
||||
|
||||
if (!lvcc->pic_width_in_luma_samples || !lvcc->pic_height_in_luma_samples)
|
||||
break;
|
||||
|
||||
avio_write(pb, raw_gbc.buffer, raw_block_size);
|
||||
nalu_length += raw_block_size;
|
||||
gc = 1;
|
||||
break;
|
||||
}
|
||||
case 5:
|
||||
avio_write(pb, raw_gbc.buffer, raw_block_size);
|
||||
nalu_length += raw_block_size;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
bytestream2_skip(&gbc, block_size);
|
||||
bytestream2_skip(&raw_gbc, raw_block_size);
|
||||
}
|
||||
|
||||
if (!sc || !gc)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
avio_w8(pb, 0x80); // rbsp_alignment bits
|
||||
|
||||
end = avio_tell(pb);
|
||||
avio_seek(pb, start, SEEK_SET);
|
||||
avio_wb16(pb, nalu_length);
|
||||
avio_seek(pb, end, SEEK_SET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ff_isom_write_lvcc(AVIOContext *pb, const uint8_t *data, int len)
|
||||
{
|
||||
LCEVCDecoderConfigurationRecord lvcc = { 0 };
|
||||
AVIOContext *idr_pb = NULL, *nidr_pb = NULL;
|
||||
H2645Packet h2645_pkt = { 0 };
|
||||
uint8_t *idr, *nidr;
|
||||
uint32_t idr_size = 0, nidr_size = 0;
|
||||
int ret, nb_idr = 0, nb_nidr = 0;
|
||||
|
||||
if (len <= 6)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
/* check for start code */
|
||||
if (AV_RB32(data) != 0x00000001 &&
|
||||
AV_RB24(data) != 0x000001) {
|
||||
avio_write(pb, data, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = ff_h2645_packet_split(&h2645_pkt, data, len, NULL, 0, AV_CODEC_ID_LCEVC, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = avio_open_dyn_buf(&idr_pb);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
ret = avio_open_dyn_buf(&nidr_pb);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
/* look for IDR or NON_IDR */
|
||||
for (int i = 0; i < h2645_pkt.nb_nals; i++) {
|
||||
const H2645NAL *nal = &h2645_pkt.nals[i];
|
||||
|
||||
if (nal->type == LCEVC_IDR_NUT) {
|
||||
nb_idr++;
|
||||
|
||||
ret = write_nalu(&lvcc, idr_pb, nal);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else if (nal->type == LCEVC_NON_IDR_NUT) {
|
||||
nb_nidr++;
|
||||
|
||||
ret = write_nalu(&lvcc, nidr_pb, nal);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
idr_size = avio_get_dyn_buf(idr_pb, &idr);
|
||||
nidr_size = avio_get_dyn_buf(nidr_pb, &nidr);
|
||||
|
||||
if (!idr_size && !nidr_size) {
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
avio_w8(pb, 1); /* version */
|
||||
avio_w8(pb, lvcc.profile_idc);
|
||||
avio_w8(pb, lvcc.level_idc);
|
||||
avio_w8(pb, (lvcc.chroma_format_idc << 6) |
|
||||
(lvcc.bit_depth_luma_minus8 << 3) |
|
||||
lvcc.bit_depth_chroma_minus8);
|
||||
avio_w8(pb, 0xff); /* 2 bits nal size length - 1 (11) + 6 bits reserved (111111)*/
|
||||
avio_wb32(pb, lvcc.pic_width_in_luma_samples);
|
||||
avio_wb32(pb, lvcc.pic_height_in_luma_samples);
|
||||
avio_w8(pb, 0xff);
|
||||
|
||||
int nb_arrays = !!nb_idr + !!nb_nidr;
|
||||
avio_w8(pb, nb_arrays);
|
||||
|
||||
if (nb_idr) {
|
||||
avio_w8(pb, LCEVC_IDR_NUT);
|
||||
avio_wb16(pb, nb_idr);
|
||||
avio_write(pb, idr, idr_size);
|
||||
}
|
||||
if (nb_nidr) {
|
||||
avio_w8(pb, LCEVC_NON_IDR_NUT);
|
||||
avio_wb16(pb, nb_idr);
|
||||
avio_write(pb, nidr, nidr_size);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
fail:
|
||||
ffio_free_dyn_buf(&idr_pb);
|
||||
ffio_free_dyn_buf(&nidr_pb);
|
||||
ff_h2645_packet_uninit(&h2645_pkt);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* LCEVC helper functions for muxers
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVFORMAT_LCEVC_H
|
||||
#define AVFORMAT_LCEVC_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "avio.h"
|
||||
|
||||
int ff_isom_write_lvcc(AVIOContext *pb, const uint8_t *data, int len);
|
||||
|
||||
#endif /* AVFORMAT_LCEVC_H */
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "libavcodec/lcevctab.c"
|
||||
+79
-2
@@ -38,6 +38,7 @@
|
||||
#include "avc.h"
|
||||
#include "evc.h"
|
||||
#include "apv.h"
|
||||
#include "lcevc.h"
|
||||
#include "libavcodec/ac3_parser_internal.h"
|
||||
#include "libavcodec/dnxhddata.h"
|
||||
#include "libavcodec/flac.h"
|
||||
@@ -1681,6 +1682,19 @@ static int mov_write_evcc_tag(AVIOContext *pb, MOVTrack *track)
|
||||
return update_size(pb, pos);
|
||||
}
|
||||
|
||||
static int mov_write_lvcc_tag(AVIOContext *pb, MOVTrack *track)
|
||||
{
|
||||
int64_t pos = avio_tell(pb);
|
||||
|
||||
avio_wb32(pb, 0);
|
||||
ffio_wfourcc(pb, "lvcC");
|
||||
|
||||
ff_isom_write_lvcc(pb, track->extradata[track->last_stsd_index],
|
||||
track->extradata_size[track->last_stsd_index]);
|
||||
|
||||
return update_size(pb, pos);
|
||||
}
|
||||
|
||||
static int mov_write_vvcc_tag(AVIOContext *pb, MOVTrack *track)
|
||||
{
|
||||
int64_t pos = avio_tell(pb);
|
||||
@@ -2880,6 +2894,8 @@ static int mov_write_video_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex
|
||||
}
|
||||
else if (track->par->codec_id ==AV_CODEC_ID_EVC) {
|
||||
mov_write_evcc_tag(pb, track);
|
||||
} else if (track->par->codec_id == AV_CODEC_ID_LCEVC) {
|
||||
mov_write_lvcc_tag(pb, track);
|
||||
} else if (track->par->codec_id ==AV_CODEC_ID_APV) {
|
||||
mov_write_apvc_tag(mov->fc, pb, track);
|
||||
} else if (track->par->codec_id == AV_CODEC_ID_VP9) {
|
||||
@@ -5222,6 +5238,9 @@ static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov,
|
||||
if (track->tag == MKTAG('r','t','p',' ')) {
|
||||
track->tref_tag = MKTAG('h','i','n','t');
|
||||
track->tref_id = mov->tracks[track->src_track].track_id;
|
||||
} else if (track->tag == MKTAG('l','v','c','1')) {
|
||||
track->tref_tag = MKTAG('s','b','a','s');
|
||||
track->tref_id = mov->tracks[track->src_track].track_id;
|
||||
} else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||
const AVPacketSideData *sd = av_packet_side_data_get(track->st->codecpar->coded_side_data,
|
||||
track->st->codecpar->nb_coded_side_data,
|
||||
@@ -6847,6 +6866,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
par->codec_id == AV_CODEC_ID_VVC ||
|
||||
par->codec_id == AV_CODEC_ID_VP9 ||
|
||||
par->codec_id == AV_CODEC_ID_EVC ||
|
||||
par->codec_id == AV_CODEC_ID_LCEVC ||
|
||||
par->codec_id == AV_CODEC_ID_TRUEHD) && !trk->extradata_size[0] &&
|
||||
!TAG_IS_AVCI(trk->tag)) {
|
||||
/* copy frame to create needed atoms */
|
||||
@@ -6957,6 +6977,25 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
} else {
|
||||
size = ff_vvc_annexb2mp4(pb, pkt->data, pkt->size, 0, NULL);
|
||||
}
|
||||
} else if (par->codec_id == AV_CODEC_ID_LCEVC && trk->extradata_size[trk->last_stsd_index] > 0 &&
|
||||
*(uint8_t *)trk->extradata[trk->last_stsd_index] != 1) {
|
||||
/* extradata is Annex B, assume the bitstream is too and convert it */
|
||||
if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) {
|
||||
ret = ff_nal_parse_units_buf(pkt->data, &reformatted_data, &size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
avio_write(pb, reformatted_data, size);
|
||||
} else {
|
||||
if (trk->cenc.aes_ctr) {
|
||||
size = ff_mov_cenc_avc_parse_nal_units(&trk->cenc, pb, pkt->data, size);
|
||||
if (size < 0) {
|
||||
ret = size;
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
size = ff_nal_parse_units(pb, pkt->data, pkt->size);
|
||||
}
|
||||
}
|
||||
} else if (par->codec_id == AV_CODEC_ID_AV1 && !trk->cenc.aes_ctr) {
|
||||
if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) {
|
||||
ret = ff_av1_filter_obus_buf(pkt->data, &reformatted_data,
|
||||
@@ -8041,10 +8080,25 @@ static int mov_init(AVFormatContext *s)
|
||||
s->streams[0]->disposition |= AV_DISPOSITION_DEFAULT;
|
||||
}
|
||||
|
||||
#if CONFIG_IAMFENC
|
||||
for (i = 0; i < s->nb_stream_groups; i++) {
|
||||
AVStreamGroup *stg = s->stream_groups[i];
|
||||
|
||||
if (stg->type == AV_STREAM_GROUP_PARAMS_LCEVC) {
|
||||
if (stg->nb_streams != 2) {
|
||||
av_log(s, AV_LOG_ERROR, "Exactly two Streams are supported for Stream Groups of type LCEVC\n");
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
AVStreamGroupLCEVC *lcevc = stg->params.lcevc;
|
||||
if (lcevc->lcevc_index > 1)
|
||||
return AVERROR(EINVAL);
|
||||
AVStream *st = stg->streams[lcevc->lcevc_index];
|
||||
if (st->codecpar->codec_id != AV_CODEC_ID_LCEVC) {
|
||||
av_log(s, AV_LOG_ERROR, "Stream #%u is not an LCEVC stream\n", lcevc->lcevc_index);
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_IAMFENC
|
||||
if (stg->type != AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
|
||||
continue;
|
||||
|
||||
@@ -8062,8 +8116,8 @@ static int mov_init(AVFormatContext *s)
|
||||
|
||||
if (!mov->nb_tracks) // We support one track for the entire IAMF structure
|
||||
mov->nb_tracks++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
for (i = 0; i < s->nb_streams; i++) {
|
||||
AVStream *st = s->streams[i];
|
||||
@@ -8378,6 +8432,28 @@ static int mov_init(AVFormatContext *s)
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < s->nb_stream_groups; i++) {
|
||||
AVStreamGroup *stg = s->stream_groups[i];
|
||||
|
||||
if (stg->type != AV_STREAM_GROUP_PARAMS_LCEVC)
|
||||
continue;
|
||||
|
||||
AVStreamGroupLCEVC *lcevc = stg->params.lcevc;
|
||||
AVStream *st = stg->streams[lcevc->lcevc_index];
|
||||
MOVTrack *track = st->priv_data;
|
||||
|
||||
for (i = 0; i < mov->nb_tracks; i++) {
|
||||
MOVTrack *trk = &mov->tracks[i];
|
||||
|
||||
if (trk->st == stg->streams[!lcevc->lcevc_index])
|
||||
break;
|
||||
}
|
||||
track->src_track = i;
|
||||
|
||||
track->par->width = lcevc->width;
|
||||
track->par->height = track->height = lcevc->height;
|
||||
}
|
||||
|
||||
enable_tracks(s);
|
||||
return 0;
|
||||
}
|
||||
@@ -8892,6 +8968,7 @@ static const AVCodecTag codec_mp4_tags[] = {
|
||||
{ AV_CODEC_ID_VVC, MKTAG('v', 'v', 'c', '1') },
|
||||
{ AV_CODEC_ID_VVC, MKTAG('v', 'v', 'i', '1') },
|
||||
{ AV_CODEC_ID_EVC, MKTAG('e', 'v', 'c', '1') },
|
||||
{ AV_CODEC_ID_LCEVC, MKTAG('l', 'v', 'c', '1') },
|
||||
{ AV_CODEC_ID_APV, MKTAG('a', 'p', 'v', '1') },
|
||||
{ AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'p', '4', 'v') },
|
||||
{ AV_CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', '4', 'v') },
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "version_major.h"
|
||||
|
||||
#define LIBAVFORMAT_VERSION_MINOR 13
|
||||
#define LIBAVFORMAT_VERSION_MICRO 100
|
||||
#define LIBAVFORMAT_VERSION_MICRO 101
|
||||
|
||||
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
|
||||
LIBAVFORMAT_VERSION_MINOR, \
|
||||
|
||||
Reference in New Issue
Block a user