From patchwork Mon Mar 28 23:24:50 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Almer X-Patchwork-Id: 35038 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:c05:b0:7a:e998:b410 with SMTP id bw5csp626160pzb; Mon, 28 Mar 2022 16:26:57 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxjfdOkgvXMgr0D6rwzw1QFeoZUnou5H7Um8peKBR4NurSwRSfR/vIGGKdZDLadgcwsWBdA X-Received: by 2002:a05:6402:2806:b0:418:e956:129d with SMTP id h6-20020a056402280600b00418e956129dmr405433ede.263.1648510017620; Mon, 28 Mar 2022 16:26:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1648510017; cv=none; d=google.com; s=arc-20160816; b=wnTWjmi96qlkcj8XcSi13PC9iqjj0cDM1r0sUZxNBRF7xc1JxR2MGXNHGwIN2+7gfF WPTVPjeprUDQwKaJn1mkORy9oqPd7P0uiG0Ika0vlyZhGXt7lxFlKcVSa7puiegl5u2m CDzK3ZiDYkyg6Qt2frPuHoC+kXPhvz+gGXoziQ3KmRG+JH7rY1HQ0wG2QojRJeThzBcM vOHZV23lnajiDcC+f0S2WoGhxxgi6ogDfgiiz6TtFJFcusy5eB8XXjIkJ2lY3zxz/V3K QaSKSmNbFwuUYp46uktB2jMYKUeZsimxsPAY4QDF/TjFxNkq1DPjWOaYn7XDGxboilCf EUrg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:dkim-signature:delivered-to; bh=nf72Dm3IIa5XUCRRolN8vk7050rNRtwbjcH6LxqGEoU=; b=DMFPkITKaTGJNU+PpfvfxOTYbOQ9tg0dRJ71tgeh5YXV4iflD3Zp568Tf/Eo6W+gXl RSVKPQ4WeicHryl0AiCKWupHJ5QHpBFSG7gW2VtoMNYtFUpQwa3eRHXcEp2jptdN7UoI fFhShGZdEJU2FSfDJGZYnFBVPY3FPI0YfESnW+grwheMfZiAGDhByq/aADX4kEKLf+1r AFwlzNEM5uXxcjvjTZkjjwhtQmW/qz1IcYJMvkiaspShNBZ0sKpVNI2jC/jCf80eepYm iGQ49oVWH/77fe1DWxtt8oo+4lJLAAZBF6khsiAUUX0e16eVFkkJKu1sGMOoaYywvhYp wtNg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=HUzB0sJo; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id q25-20020a170906941900b006e06b168341si14961628ejx.754.2022.03.28.16.26.37; Mon, 28 Mar 2022 16:26:57 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=HUzB0sJo; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 27E4168B2E1; Tue, 29 Mar 2022 02:25:58 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-oi1-f180.google.com (mail-oi1-f180.google.com [209.85.167.180]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id EA4AC68B2CC for ; Tue, 29 Mar 2022 02:25:49 +0300 (EEST) Received: by mail-oi1-f180.google.com with SMTP id k10so17382900oia.0 for ; Mon, 28 Mar 2022 16:25:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=TiT6Q8IHLWLEVqdTUJYFFww7tnRXpqBtnW8v9+eIuh4=; b=HUzB0sJo+4DnLF8wUp6jJfDlpa89vFCQQ6y5wOEIhGB3cx93WvqmklOSHc04mt6emh U2W/5T1dR4XyYw0He6N71vAxqDJhLFtpKlLGT7MNjRb9PIZW/cWNCm0nS2xNSSCzOQUl qgCOt13bi5ZlZRUdFZAWhPB5jATmGiVzYq3E+plmT7JSgYnwkHLtzFPl6tU3cX/AKlmi 0hFA1J1NihwfrhbwK3sgAnwmx3DmRNBtZs0QyXA2N8nnHM3OrRtHANcp3Mg7H9j18rzw 8Go9i20WtYyTK7EwcaRs2LaSMvO8c4jMsv6UaWcarlYM86zu0nULvp7gbYDZo9D8UuNZ U7cg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=TiT6Q8IHLWLEVqdTUJYFFww7tnRXpqBtnW8v9+eIuh4=; b=uOg6YjyR/Wt90Uw6IDWNTgqA+7oge7zL39JlRCiNUSTZv8OzcWpKFuaiMDnxeCXIjq 5Ni3VV58BUiz9QWnZ8IdnyuitUxwnAtkiMxojpFZH024PEuVxumocyCJ6t+GpEp536np DaRdh1vt7bdbbu/vjcGtzHPF6N93EhqKw9n8oIhKFzVI+ESlDH45QasT68vedD2LkFzk q+V5XMs13gPgIkiCkjrQG6tXLjvSd+GKVsT0hr9/FjwD16zwX9lZhNSUIlVhHPeoRDHI kOqbNi7ODPUdm1ostIN9agTmzHixp5TwmMTLWeQdGxdxFZiVJkrxOmuvJmr274u6A7xf avew== X-Gm-Message-State: AOAM533oGzQ7+vZO8qEMPwdXuGWIxgcZSJbfGL4yUntUUb1GHMGLx+9e 2uck6bpEwrXNEcmLlKc0nNE0LMUQRAnZMw== X-Received: by 2002:aca:3643:0:b0:2ec:cb84:c5ba with SMTP id d64-20020aca3643000000b002eccb84c5bamr847713oia.183.1648509948210; Mon, 28 Mar 2022 16:25:48 -0700 (PDT) Received: from localhost.localdomain ([186.136.131.95]) by smtp.gmail.com with ESMTPSA id gk6-20020a0568703c0600b000de4880b357sm7198456oab.50.2022.03.28.16.25.47 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 28 Mar 2022 16:25:47 -0700 (PDT) From: James Almer To: ffmpeg-devel@ffmpeg.org Date: Mon, 28 Mar 2022 20:24:50 -0300 Message-Id: <20220328232453.54773-4-jamrial@gmail.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220328232453.54773-1-jamrial@gmail.com> References: <20220328232453.54773-1-jamrial@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 4/7] avformat/movenc: write channel descriptions when a known layout or a bitmap can't be used X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: qgw/wqAOf4nE Fixes part of ticket #2865 Signed-off-by: James Almer --- libavformat/mov_chan.c | 75 ++++++++++++++++++++++++++++++++---------- libavformat/mov_chan.h | 8 +++-- libavformat/movenc.c | 37 +++++++++++++++------ 3 files changed, 90 insertions(+), 30 deletions(-) diff --git a/libavformat/mov_chan.c b/libavformat/mov_chan.c index 3c23142f35..4cb373d1b9 100644 --- a/libavformat/mov_chan.c +++ b/libavformat/mov_chan.c @@ -504,9 +504,29 @@ static uint64_t mov_get_channel_mask(uint32_t label) return 0; } -uint32_t ff_mov_get_channel_layout_tag(enum AVCodecID codec_id, - const AVChannelLayout *ch_layout, - uint32_t *bitmap) +static uint32_t mov_get_channel_label(enum AVChannel channel) +{ + if (channel < 0) + return 0; + if (channel <= AV_CHAN_TOP_BACK_RIGHT) + return channel + 1; + if (channel == AV_CHAN_WIDE_LEFT) + return 35; + if (channel == AV_CHAN_WIDE_RIGHT) + return 36; + if (channel == AV_CHAN_LOW_FREQUENCY_2) + return 37; + if (channel == AV_CHAN_STEREO_LEFT) + return 38; + if (channel == AV_CHAN_STEREO_RIGHT) + return 39; + return 0; +} + +int ff_mov_get_channel_layout_tag(const AVCodecParameters *par, + uint32_t *layout, + uint32_t *bitmap, + uint32_t **pchannel_desc) { int i, j; uint32_t tag = 0; @@ -514,7 +534,7 @@ uint32_t ff_mov_get_channel_layout_tag(enum AVCodecID codec_id, /* find the layout list for the specified codec */ for (i = 0; mov_codec_ch_layouts[i].codec_id != AV_CODEC_ID_NONE; i++) { - if (mov_codec_ch_layouts[i].codec_id == codec_id) + if (mov_codec_ch_layouts[i].codec_id == par->codec_id) break; } if (mov_codec_ch_layouts[i].codec_id != AV_CODEC_ID_NONE) @@ -525,7 +545,7 @@ uint32_t ff_mov_get_channel_layout_tag(enum AVCodecID codec_id, const struct MovChannelLayoutMap *layout_map; /* get the layout map based on the channel count */ - channels = ch_layout->nb_channels; + channels = par->ch_layout.nb_channels; if (channels > 9) channels = 0; layout_map = mov_ch_layout_map[channels]; @@ -536,8 +556,8 @@ uint32_t ff_mov_get_channel_layout_tag(enum AVCodecID codec_id, continue; for (j = 0; layout_map[j].tag != 0; j++) { if (layout_map[j].tag == layouts[i] && - (ch_layout->order == AV_CHANNEL_ORDER_NATIVE && - layout_map[j].layout == ch_layout->u.mask)) + (par->ch_layout.order == AV_CHANNEL_ORDER_NATIVE && + layout_map[j].layout == par->ch_layout.u.mask)) break; } if (layout_map[j].tag) @@ -546,18 +566,39 @@ uint32_t ff_mov_get_channel_layout_tag(enum AVCodecID codec_id, tag = layouts[i]; } - /* if no tag was found, use channel bitmap as a backup if possible */ - if (tag == 0 && av_channel_layout_check(ch_layout) && - ch_layout->order == AV_CHANNEL_ORDER_NATIVE && - ch_layout->u.mask < 0x40000) { - tag = MOV_CH_LAYOUT_USE_BITMAP; - *bitmap = (uint32_t)ch_layout->u.mask; - } else - *bitmap = 0; + *layout = tag; + *bitmap = 0; + *pchannel_desc = NULL; + + /* if no tag was found, use channel bitmap or description as a backup if possible */ + if (tag == 0) { + uint32_t *channel_desc; + if (par->ch_layout.order == AV_CHANNEL_ORDER_NATIVE && + par->ch_layout.u.mask < 0x40000) { + *layout = MOV_CH_LAYOUT_USE_BITMAP; + *bitmap = (uint32_t)par->ch_layout.u.mask; + return 0; + } else if (par->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) + return AVERROR(ENOSYS); + + channel_desc = av_malloc_array(par->ch_layout.nb_channels, sizeof(*channel_desc)); + if (!channel_desc) + return AVERROR(ENOMEM); + + for (i = 0; i < par->ch_layout.nb_channels; i++) { + channel_desc[i] = + mov_get_channel_label(av_channel_layout_channel_from_index(&par->ch_layout, i)); + + if (channel_desc[i] == 0) { + av_free(channel_desc); + return AVERROR(ENOSYS); + } + } - /* TODO: set channel descriptions as a secondary backup */ + *pchannel_desc = channel_desc; + } - return tag; + return 0; } int ff_mov_read_chan(AVFormatContext *s, AVIOContext *pb, AVStream *st, diff --git a/libavformat/mov_chan.h b/libavformat/mov_chan.h index 9514dfa405..2815f15f07 100644 --- a/libavformat/mov_chan.h +++ b/libavformat/mov_chan.h @@ -30,6 +30,7 @@ #include "libavutil/channel_layout.h" #include "libavcodec/codec_id.h" +#include "libavcodec/codec_par.h" #include "avformat.h" /** @@ -41,9 +42,10 @@ * @param[out] bitmap channel bitmap * @return channel layout tag */ -uint32_t ff_mov_get_channel_layout_tag(enum AVCodecID codec_id, - const AVChannelLayout *ch_layout, - uint32_t *bitmap); +int ff_mov_get_channel_layout_tag(const AVCodecParameters *par, + uint32_t *layout, + uint32_t *bitmap, + uint32_t **pchannel_desc); /** * Read 'chan' tag from the input stream. diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 46d66c29c2..263649f1da 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -867,20 +867,27 @@ static int mov_write_dmlp_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra static int mov_write_chan_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) { - uint32_t layout_tag, bitmap; + uint32_t layout_tag, bitmap, *channel_desc; int64_t pos = avio_tell(pb); + int num_desc, ret; - layout_tag = ff_mov_get_channel_layout_tag(track->par->codec_id, - &track->par->ch_layout, - &bitmap); - if (!layout_tag) { - av_log(s, AV_LOG_WARNING, "not writing 'chan' tag due to " - "lack of channel information\n"); + if (track->multichannel_as_mono) return 0; + + ret = ff_mov_get_channel_layout_tag(track->par, &layout_tag, + &bitmap, &channel_desc); + + if (ret < 0) { + if (ret == AVERROR(ENOSYS)) { + av_log(s, AV_LOG_WARNING, "not writing 'chan' tag due to " + "lack of channel information\n"); + ret = 0; + } + + return ret; } - if (track->multichannel_as_mono) - return 0; + num_desc = layout_tag ? 0 : track->par->ch_layout.nb_channels; avio_wb32(pb, 0); // Size ffio_wfourcc(pb, "chan"); // Type @@ -888,7 +895,17 @@ static int mov_write_chan_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra avio_wb24(pb, 0); // Flags avio_wb32(pb, layout_tag); // mChannelLayoutTag avio_wb32(pb, bitmap); // mChannelBitmap - avio_wb32(pb, 0); // mNumberChannelDescriptions + avio_wb32(pb, num_desc); // mNumberChannelDescriptions + + for (int i = 0; i < num_desc; i++) { + avio_wb32(pb, channel_desc[i]); // mChannelLabel + avio_wb32(pb, 0); // mChannelFlags + avio_wl32(pb, 0); // mCoordinates[0] + avio_wl32(pb, 0); // mCoordinates[1] + avio_wl32(pb, 0); // mCoordinates[2] + } + + av_free(channel_desc); return update_size(pb, pos); }