@@ -39,6 +39,7 @@
#include "libavutil/log.h"
#include "libavutil/pixfmt.h"
#include "libavutil/rational.h"
+#include "libavutil/channel_layout_isoiec23001_8.h"
#include "version.h"
@@ -1368,6 +1369,69 @@ typedef struct AVTrackReferences {
/** followed by an optional gap for alignment purposes and another AVTrackReferences is applicaple */
} AVTrackReferences;
+/**
+ * Describes the speaker position of a single audio channel of a single track
+ *
+ * The name is chosen in a slightly obscure manner as to allow a more
+ * natural name to take its place when the system supports FFmpeg's
+ * native channel positions.
+ */
+typedef struct AVAudioTrackChannelPositionISOIEC23001_8 {
+ AVSpeakerPositionISOIEC23001_8 speaker_position; /**< an OutputChannelPosition from ISO/IEC 23001-8 */
+
+ /** The following are used if speaker_position == AV_SPEAKER_POSITION_ISOIEC23001_8_EXPL */
+ int16_t azimuth; /**< Degrees -180..180. Values increment counterclockwise from above. */
+ int8_t elevation; /**< Degrees -90..90. >0 is above horizon. */
+} AVAudioTrackChannelPositionISOIEC23001_8;
+
+/**
+ * Describes the channel layout (ie. speaker position) of a single audio track
+ *
+ * The name is chosen in a slightly obscure manner as to allow a more
+ * natural name to take its place when the system supports FFmpeg's
+ * native channel positions.
+ */
+typedef struct AVAudioTrackChannelCompleteLayoutISOIEC23001_8 {
+ int nb_positions;
+ AVAudioTrackChannelPositionISOIEC23001_8 positions[64];
+} AVAudioTrackChannelCompleteLayoutISOIEC23001_8;
+
+/**
+ * Describes the channel layout based on predefined layout of a single
+ * track by providing the layout and the list of channels are are
+ * omitted. For example, you may choose a layout that has 6.1 channels
+ * and then choose to omit the LFE channel from your channels.
+ *
+ * The name is chosen in a slightly obscure manner as to allow a more natural
+ * name to take its place when the system supports FFmpeg's native layouts.
+ */
+typedef struct AVAudioTrackChannelPredefinedLayoutISOIEC23001_8 {
+ AVChannelLayoutISOIEC23001_8 layout; /**< ChannelConfiguration from ISO/IEC 23001-8 */
+ uint64_t omitted_channels; /**< lsb 1 means the first channel is omitted and so on */
+} AVAudioTrackChannelPredefinedLayoutISOIEC23001_8;
+
+typedef enum AVComplexAudioTrackChannelLayoutType {
+ AV_COMPLEX_CHANNEL_LAYOUT_OBJECTS_ONLY,
+ AV_COMPLEX_CHANNEL_LAYOUT_PREDEFINED_ISOIEC23001_8,
+ AV_COMPLEX_CHANNEL_LAYOUT_COMPLETE_ISOIEC23001_8,
+} AVComplexAudioTrackChannelLayoutType;
+
+typedef struct AVAudioTrackChannelLayout {
+ AVComplexAudioTrackChannelLayoutType type;
+ union {
+ AVAudioTrackChannelPredefinedLayoutISOIEC23001_8 predefined;
+ AVAudioTrackChannelCompleteLayoutISOIEC23001_8 complete;
+ };
+
+ /**
+ * Describes the channel layout to be object-structured with given
+ * number of objects. Object-structured audio is means to describe
+ * an audio scene without a fixed channel layout that can be mixed
+ * to varying channel configurations.
+ */
+ int nb_audio_objects; /**< Number of audio objects */
+} AVAudioTrackChannelLayout;
+
enum AVPacketSideDataType {
AV_PKT_DATA_PALETTE,
@@ -1562,6 +1626,13 @@ enum AVPacketSideDataType {
AV_PKT_DATA_TIMED_METADATA_INFO,
/**
+ * Channel layout, describing the position of spakers for the
+ * channels of a track, following the structure
+ * AVAudioTrackChannelLayout.
+ */
+ AV_PKT_DATA_AUDIO_TRACK_CHANNEL_LAYOUT,
+
+ /**
* Assign alternate groups for tracks. An example of alternate
* groups would be audio tracks (or video tracks) that are
* alternative to each other. Each alternative track shares the
@@ -557,6 +557,89 @@ static unsigned compute_avg_bitrate(MOVTrack *track)
return size * 8 * track->timescale / track->track_duration;
}
+static int mov_write_chnl_tag(AVIOContext *pb, MOVTrack *track)
+{
+ AVAudioTrackChannelLayout *side_data =
+ (void*) av_stream_get_side_data(track->st, AV_PKT_DATA_AUDIO_TRACK_CHANNEL_LAYOUT,
+ NULL);
+
+ if (!side_data) {
+ return 0;
+ } else {
+ AVAudioTrackChannelPredefinedLayoutISOIEC23001_8 *predefined =
+ side_data && side_data->type == AV_COMPLEX_CHANNEL_LAYOUT_PREDEFINED_ISOIEC23001_8
+ ? &side_data->predefined
+ : NULL;
+
+ AVAudioTrackChannelCompleteLayoutISOIEC23001_8 *complete =
+ side_data && side_data->type == AV_COMPLEX_CHANNEL_LAYOUT_COMPLETE_ISOIEC23001_8
+ ? &side_data->complete
+ : NULL;
+
+ int object_count = side_data ? side_data->nb_audio_objects : 0;
+
+ int64_t pos = avio_tell(pb);
+
+ int channel_structured = predefined || complete;
+ int object_structured = !!object_count;
+
+ // ChannelConfiguration from ISO/IEC 23001-8
+ int defined_layout = predefined ? predefined->layout : 0;
+ int channel_count = track->par->channels;
+
+ int stream_structure = (channel_structured << 0) | (object_structured << 1);
+
+ if (object_count < 0 ||
+ defined_layout < 0)
+ return AVERROR(EINVAL);
+
+ avio_wb32(pb, 0); // size
+ ffio_wfourcc(pb, "chnl");
+ avio_wb32(pb, 0); // Version
+
+ avio_w8(pb, stream_structure);
+
+ if (channel_structured) {
+ avio_w8(pb, defined_layout);
+ if (defined_layout == 0) {
+ AVAudioTrackChannelPositionISOIEC23001_8* positions;
+ int i;
+
+ if (!complete)
+ goto error;
+
+ if (complete->nb_positions > channel_count)
+ goto error;
+
+ positions = complete->positions;
+
+ for (i = 0; i < channel_count; ++i) {
+ AVAudioTrackChannelPositionISOIEC23001_8 *pos = &positions[i];
+ avio_w8(pb, pos->speaker_position);
+ if (pos->speaker_position == AV_SPEAKER_POSITION_ISOIEC23001_8_EXPL) {
+ if (pos->azimuth < -180 || pos->azimuth > 180)
+ return AVERROR(EINVAL);
+ avio_wb16(pb, pos->azimuth);
+ avio_w8(pb, pos->elevation);
+ }
+ }
+ } else {
+ if (!predefined)
+ goto error;
+
+ avio_wb64(pb, predefined->omitted_channels);
+ }
+ }
+ if (object_structured)
+ avio_w8(pb, object_count);
+
+ return update_size(pb, pos);
+ error:
+ update_size(pb, pos);
+ return AVERROR(EINVAL);
+ }
+}
+
static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic
{
AVCPBProperties *props;
@@ -996,8 +1079,10 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex
(mov_pcm_le_gt16(track->par->codec_id) && version==1) ||
(mov_pcm_be_gt16(track->par->codec_id) && version==1)))
mov_write_wave_tag(s, pb, track);
- else if (track->tag == MKTAG('m','p','4','a'))
+ else if (track->tag == MKTAG('m','p','4','a')) {
+ mov_write_chnl_tag(pb, track);
mov_write_esds_tag(pb, track);
+ }
else if (track->par->codec_id == AV_CODEC_ID_AMR_NB)
mov_write_amr_tag(pb, track);
else if (track->par->codec_id == AV_CODEC_ID_AC3)
new file mode 100644
@@ -0,1 +1,97 @@
+/*
+ * copyright (c) 2016 Erkki Seppälä <erkki.seppala.ext@nokia.com>
+ *
+ * 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 AVUTIL_CHANNEL_LAYOUT_ISOIEC23001_8_H
+#define AVUTIL_CHANNEL_LAYOUT_ISOIEC23001_8_H
+
+/** Speaker positions according to ISO/IEC 23001-8 */
+typedef enum AVSpeakerPositionISOIEC23001_8 {
+ AV_SPEAKER_POSITION_ISOIEC23001_8_L = 0, //< Left front
+ AV_SPEAKER_POSITION_ISOIEC23001_8_R = 1, //< Right front
+ AV_SPEAKER_POSITION_ISOIEC23001_8_C = 2, //< Centre front
+ AV_SPEAKER_POSITION_ISOIEC23001_8_LFE = 3, //< Low frequency enhancement
+ AV_SPEAKER_POSITION_ISOIEC23001_8_LS = 4, //< Left surround
+ AV_SPEAKER_POSITION_ISOIEC23001_8_RS = 5, //< Right surround
+ AV_SPEAKER_POSITION_ISOIEC23001_8_LC = 6, //< Left front centre
+ AV_SPEAKER_POSITION_ISOIEC23001_8_RC = 7, //< Right front centre
+ AV_SPEAKER_POSITION_ISOIEC23001_8_LSR = 8, //< Rear surround left
+ AV_SPEAKER_POSITION_ISOIEC23001_8_RSR = 9, //< Rear surround right
+ AV_SPEAKER_POSITION_ISOIEC23001_8_CS = 10, //< Rear centre
+ AV_SPEAKER_POSITION_ISOIEC23001_8_LSD = 11, //< Left surround direct
+ AV_SPEAKER_POSITION_ISOIEC23001_8_RSD = 12, //< Right surround direct
+ AV_SPEAKER_POSITION_ISOIEC23001_8_LSS = 13, //< Left side surround
+ AV_SPEAKER_POSITION_ISOIEC23001_8_RSS = 14, //< Right side surround
+ AV_SPEAKER_POSITION_ISOIEC23001_8_LW = 15, //< Left wide front
+ AV_SPEAKER_POSITION_ISOIEC23001_8_RW = 16, //< Right wide front
+ AV_SPEAKER_POSITION_ISOIEC23001_8_LV = 17, //< Left front vertical height
+ AV_SPEAKER_POSITION_ISOIEC23001_8_RV = 18, //< Right front vertical height
+ AV_SPEAKER_POSITION_ISOIEC23001_8_CV = 19, //< Centre front vertical height
+ AV_SPEAKER_POSITION_ISOIEC23001_8_LVR = 20, //< Left surround vertical height rear
+ AV_SPEAKER_POSITION_ISOIEC23001_8_RVR = 21, //< Right surround vertical height rear
+ AV_SPEAKER_POSITION_ISOIEC23001_8_CVR = 22, //< Centre vertical height rear
+ AV_SPEAKER_POSITION_ISOIEC23001_8_LVSS = 23, //< Left vertical height side surround
+ AV_SPEAKER_POSITION_ISOIEC23001_8_RVSS = 24, //< Right vertical height side surround
+ AV_SPEAKER_POSITION_ISOIEC23001_8_TS = 25, //< Top centre surround
+ AV_SPEAKER_POSITION_ISOIEC23001_8_LFE2 = 26, //< E2 Low frequency enhancement 2
+ AV_SPEAKER_POSITION_ISOIEC23001_8_LB = 27, //< Left front vertical bottom
+ AV_SPEAKER_POSITION_ISOIEC23001_8_RB = 28, //< Right front vertical bottom
+ AV_SPEAKER_POSITION_ISOIEC23001_8_CB = 29, //< Centre front vertical bottom
+ AV_SPEAKER_POSITION_ISOIEC23001_8_LVS = 30, //< Left vertical height surround
+ AV_SPEAKER_POSITION_ISOIEC23001_8_RVS = 31, //< Right vertical height surround
+ //< 32-45 Reserved
+ AV_SPEAKER_POSITION_ISOIEC23001_8_LFE3 = 36, //< E3 Low frequency enhancement 3
+ AV_SPEAKER_POSITION_ISOIEC23001_8_LEOS = 37, //< Left edge of screen
+ AV_SPEAKER_POSITION_ISOIEC23001_8_REOS = 38, //< Right edge of screen
+ AV_SPEAKER_POSITION_ISOIEC23001_8_HWBCAL = 39, //< half-way between centre of screen and left edge of screen
+ AV_SPEAKER_POSITION_ISOIEC23001_8_HWBCAR = 40, //< half-way between centre of screen and right edge of screen
+ AV_SPEAKER_POSITION_ISOIEC23001_8_LBS = 41, //< Left back surround
+ AV_SPEAKER_POSITION_ISOIEC23001_8_RBS = 42, //< Right back surround
+ //< 43–125 Reserved
+ AV_SPEAKER_POSITION_ISOIEC23001_8_EXPL = 126, //< Explicit position (see text)
+ //< 127 Unknown / undefined
+} AVSpeakerPositionISOIEC23001_8;
+
+/** Channel layouts according to ISO/IEC 23001-8 */
+typedef enum AVChannelLayoutISOIEC23001_8 {
+ AV_CH_LAYOUT_ISOIEC23001_8_ANY,
+ AV_CH_LAYOUT_ISOIEC23001_8_1_0_0, //< 1 centre front
+ AV_CH_LAYOUT_ISOIEC23001_8_2_0_0, //< 2 left front, right front
+ AV_CH_LAYOUT_ISOIEC23001_8_3_0_0, //< 3 centre front, left front, right front
+ AV_CH_LAYOUT_ISOIEC23001_8_3_1_0, //< 4 centre front, left front, right front, rear centre
+ AV_CH_LAYOUT_ISOIEC23001_8_3_2_0, //< 5 centre front, left front, right front, left surround, right surround
+ AV_CH_LAYOUT_ISOIEC23001_8_3_2_1, //< 6 centre front, left front, right front, left surround, right surround, LFE
+ AV_CH_LAYOUT_ISOIEC23001_8_5_2_1A, //< 7 centre front, left front centre, right front centre, left front, right front, left surround, right surround, LFE
+ AV_CH_LAYOUT_ISOIEC23001_8_1P1, //< 8 channel1 channel2
+ AV_CH_LAYOUT_ISOIEC23001_8_2_1_0, //< 9 left front, right front, rear centre
+ AV_CH_LAYOUT_ISOIEC23001_8_2_2_0, //< 10 left front, right front, left surround, right surround
+ AV_CH_LAYOUT_ISOIEC23001_8_3_3_1, //< 11 centre front, left front, right front, left surround, right surround, rear centre, LFE
+ AV_CH_LAYOUT_ISOIEC23001_8_3_4_1, //< 12 centre front, left front, right front, left surround, right surround, rear surround left, rear surround right, LFE
+ AV_CH_LAYOUT_ISOIEC23001_8_11_11_2, //< 13 centre front, left front centre, right front centre, left front, right front, left side surround, right side surround, rear left surround, rear right surround, rear centre, left front LFE, right front LFE, centre front vertical height, left front vertical height, right front vertical height, left vertical height side surround, r ight vertical height side surround, top centre surround, left surround vertical height rear, r ight surround vertical height rear , centre vertical height rear, centre front vertical bottom, left front vertical bottom, right front vertical bottom
+ AV_CH_LAYOUT_ISOIEC23001_8_5_2_1B, //< 14 centre front, left front, right front, left surround, right surround, LFE, left front vertical height, right front vertical height
+ AV_CH_LAYOUT_ISOIEC23001_8_5_5_2, //< 15 centre front, left front, right front, left side surround, right side surround, left surround, right surround, left front vertical height, right front vertical height, centre vertical height rear, LFE1, LFE2
+ AV_CH_LAYOUT_ISOIEC23001_8_5_4_1, //< 16 centre front, left front, right front, left surround, right surround, LFE, left front vertical height, right front vertical height, left vertical height surround, right vertical height surround
+ AV_CH_LAYOUT_ISOIEC23001_8_6_5_1, //< 17 centre front, left front, right front, left surround, right surround, LFE, left front vertical height, right front vertical height, centre front vertical height, left vertical height surround, right vertical height surround, top centre surround
+ AV_CH_LAYOUT_ISOIEC23001_8_6_7_1, //< 18 centre front, left front, right front, left surround, right surround, left back surround, right back surround LFE, left front vertical height, right front vertical height, centre front vertical height, left vertical height surround, right vertical height surround, top centre surround
+ AV_CH_LAYOUT_ISOIEC23001_8_5_6_1, //< 19 centre front, left front, right front, left side surround, right side surround, rear surround left, rear surround right, LFE, left front vertical height, right front vertical height, left surround vertical height rear, right surround vertical height rear
+ AV_CH_LAYOUT_ISOIEC23001_8_7_6_1, //< 20 centre front, left edge of screen, right edge of screen, left front, right front, left side surround, right side surround, rear surround left, rear surround right, LFE, left front vertical height, right front vertical height, left vertical height surround, right vertical height surround
+ //< 21..63: reserved
+} AVChannelLayoutISOIEC23001_8;
+
+#endif /* AVUTIL_CHANNEL_LAYOUT_ISOIEC23001_8_H */
--