On Thu,  6 Jul 2017 17:36:39 -0700
"Louis O'Bryan" <lboext...@gmail.com> wrote:

> From: Louis O'Bryan <lou...@google.com>
> 
> Signed-off-by: Louis O'Bryan <lou...@google.com>
> ---
>  Changelog               |   1 +
>  doc/general.texi        |   2 +
>  libavcodec/Makefile     |   1 +
>  libavcodec/allcodecs.c  |   3 +
>  libavcodec/avcodec.h    |   1 +
>  libavcodec/cammenc.c    | 299 
> ++++++++++++++++++++++++++++++++++++++++++++++++
>  libavcodec/codec_desc.c |   6 +
>  libavcodec/version.h    |   4 +-
>  libavformat/isom.c      |   6 +
>  libavformat/movenc.c    | 200 +++++++++++++++++---------------
>  10 files changed, 431 insertions(+), 92 deletions(-)
>  create mode 100644 libavcodec/cammenc.c
> 
> diff --git a/Changelog b/Changelog
> index a8726c6736..5f98385b53 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -2,6 +2,7 @@ Entries are sorted chronologically from oldest to youngest 
> within each release,
>  releases are sorted from youngest to oldest.
>  
>  version <next>:
> +- Camera metadata motion encoder
>  - deflicker video filter
>  - doubleweave video filter
>  - lumakey video filter
> diff --git a/doc/general.texi b/doc/general.texi
> index 8f582d586f..06996c81e8 100644
> --- a/doc/general.texi
> +++ b/doc/general.texi
> @@ -912,6 +912,8 @@ following image formats are supported:
>      @tab part of LCL, encoder experimental
>  @item Zip Motion Blocks Video  @tab   X @tab  X
>      @tab Encoder works only in PAL8.
> +@item Camera metadata motion    @tab X  @tab
> +    @tab Encoder for camera sensor data.
>  @end multitable
>  
>  @code{X} means that encoding (resp. decoding) is supported.
> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> index b440a00746..306cc793ee 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -680,6 +680,7 @@ OBJS-$(CONFIG_ZLIB_DECODER)            += lcldec.o
>  OBJS-$(CONFIG_ZLIB_ENCODER)            += lclenc.o
>  OBJS-$(CONFIG_ZMBV_DECODER)            += zmbv.o
>  OBJS-$(CONFIG_ZMBV_ENCODER)            += zmbvenc.o
> +OBJS-$(CONFIG_CAMERA_MOTION_METADATA_ENCODER) += cammenc.o
>  
>  # (AD)PCM decoders/encoders
>  OBJS-$(CONFIG_PCM_ALAW_DECODER)           += pcm.o
> diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
> index 0243f47358..eff51f4042 100644
> --- a/libavcodec/allcodecs.c
> +++ b/libavcodec/allcodecs.c
> @@ -651,6 +651,9 @@ static void register_all(void)
>      REGISTER_DECODER(XBIN,              xbin);
>      REGISTER_DECODER(IDF,               idf);
>  
> +    /* data */
> +    REGISTER_ENCODER(CAMERA_MOTION_METADATA, camera_motion_metadata);
> +
>      /* external libraries, that shouldn't be used by default if one of the
>       * above is available */
>      REGISTER_ENCDEC (LIBOPENH264,       libopenh264);
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index b697afa0ae..622383f453 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -681,6 +681,7 @@ enum AVCodecID {
>      AV_CODEC_ID_DVD_NAV,
>      AV_CODEC_ID_TIMED_ID3,
>      AV_CODEC_ID_BIN_DATA,
> +    AV_CODEC_ID_CAMERA_MOTION_METADATA,
>  
>  
>      AV_CODEC_ID_PROBE = 0x19000, ///< codec_id is not known (like 
> AV_CODEC_ID_NONE) but lavf should attempt to identify it
> diff --git a/libavcodec/cammenc.c b/libavcodec/cammenc.c
> new file mode 100644
> index 0000000000..d7592ab69d
> --- /dev/null
> +++ b/libavcodec/cammenc.c
> @@ -0,0 +1,299 @@
> +/*
> + * Reference implementation for the CAMM Metadata encoder.
> + * Encodes sensor data for 360-degree cameras such as
> + * GPS, gyro, and acceleration. This is stored in a track separate from video
> + * and audio.
> + *
> + * Copyright (c) 2017 Louis O'Bryan
> + *
> + * 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
> + */
> +
> +/**
> + * CAMM Metadata encoder
> + * @author Louis O'Bryan
> + */
> +
> +#include <math.h>
> +#include <float.h>
> +#include "avcodec.h"
> +#include "internal.h"
> +#include "bytestream.h"
> +#include "libavutil/common.h"
> +#include "libavutil/opt.h"
> +
> +#define DUMMY_ENCODER_SIZE 1
> +
> +typedef struct CammContext {
> +    AVCodecContext *avctx;
> +} CammContext;
> +
> +// Sizes of each type of metadata.
> +static int metadata_type_sizes[] = {
> +  3 * sizeof(float),
> +  2 * sizeof(uint64_t),
> +  3 * sizeof(float),
> +  3 * sizeof(float),
> +  3 * sizeof(float),
> +  3 * sizeof(float),
> +  3 * sizeof(double) + sizeof(uint32_t) + 7 * sizeof(float),
> +  3 * sizeof(float)
> +};
> +
> +static int min_packet_size = sizeof(uint16_t) * 2;

We pretty much don't accept mutable global variables in new code.

> +
> +/**
> + * Validates that the latitude has a valid value. Returns 1 if ok, else 0.
> + */
> +static int validate_latitude(AVCodecContext *avctx, double latitude) {
> +    if (latitude < -M_PI / 4 || latitude > M_PI / 4) {
> +        av_log(avctx, AV_LOG_ERROR,
> +               "Latitude %f is not in bounds (%f, %f)\n",
> +               latitude, -M_PI / 4, M_PI / 4);
> +        return 0;
> +    }
> +    return 1;
> +}
> +
> +/**
> + * Validates that the longitude has a valid value. Returns 1 if ok, else 0.
> + */
> +static int validate_longitude(AVCodecContext *avctx, double longitude) {
> +    if (longitude < -M_PI / 2 || longitude > M_PI / 2) {
> +        av_log(avctx, AV_LOG_ERROR,
> +               "longitude %f is not in bounds (%f, %f)\n",
> +               longitude, -M_PI / 2, M_PI / 2);
> +        return 0;
> +    }
> +    return 1;
> +}
> +
> +static void log_float_values(AVCodecContext *avctx, const char *name, float 
> *data) {
> +    int i;
> +    float value;
> +    for (i = 0; i < 3; ++i) {
> +        value = data[i];
> +        av_log(avctx, AV_LOG_DEBUG, "%s[%d] = %f\n", name, i, value);
> +    }
> +}
> +
> +/**
> + * Validates that the incoming data is correctly formatted and returns
> + * 1 if it is, 0 otherwise.
> + */
> +static int validate_data(AVCodecContext *avctx, const AVFrame *data) {
> +    uint16_t packet_type;
> +    int expected_packet_size;
> +    uint64_t pixel_exposure_time;
> +    uint64_t rolling_shutter_skew_time;
> +    uint32_t *camm_data;
> +    double time_gps_epoch;
> +    uint32_t gps_fix_type;
> +    double latitude;
> +    double longitude;
> +    float altitude;
> +
> +    if (data->pkt_size < min_packet_size) {
> +        av_log(avctx, AV_LOG_ERROR,
> +               "CAMM input data with size %d is too small\n", 
> data->pkt_size);
> +        return 0;
> +    }

I don't think AVFrame.pkt_size should be used for any real purpose.
It's a hack and doesn't really have anything to do with AVFrame data
(the idea is that it corresponds to the source packet, but it's only a
hint at best).

I'm not sure what's the appropriate way to indicate the source data
size. Normally it's implicit (format and width/height for video, or
nb_samples for audio).

Where is the AVFrame format documented? Why is it somehow a raw byte
stream? AVFrame normally contains decoded data in a conveniently
accessible form. All this makes little sense to me to be honest.

> +
> +    packet_type = ((uint16_t*)(*data->extended_data))[1];
> +    if (packet_type > sizeof(metadata_type_sizes) / sizeof(int)) {
> +        av_log(avctx, AV_LOG_ERROR,
> +               "Packet type %d is not recognized\n", packet_type);
> +        return 0;
> +    }
> +
> +    expected_packet_size = metadata_type_sizes[packet_type];
> +    if (expected_packet_size != data->pkt_size) {
> +        av_log(avctx, AV_LOG_ERROR,
> +               "Packet size %d does not match expected size %d for type 
> %d\n",
> +               data->pkt_size, expected_packet_size, packet_type);
> +        return 0;
> +    }
> +
> +    // The actual sensor data starts after the reserved slot and packet type.
> +    camm_data = ((uint32_t*)(*data->extended_data)) + 1;
> +    switch (packet_type) {
> +        // float angle_axis[3]
> +        case 0:
> +            log_float_values(avctx, "angle_axis", (float*)camm_data);
> +            break;
> +        // int32 pixel_exposure_time
> +        // int32 rolling_shutter_skew_time
> +        case 1:
> +            pixel_exposure_time = ((uint32_t*)camm_data)[0];
> +            av_log(avctx, AV_LOG_DEBUG,
> +                   "pixel_exposure_time = %lu\n", pixel_exposure_time);
> +            rolling_shutter_skew_time = ((uint32_t*)camm_data)[1];

Maybe I'm missing context, but these accesses are not endian safe, and
we still pretend to support big endian platforms in FFmpeg. Use macros
like AV_RL32(), which were designed for this. (AVFrame data can be in
native endian, but you memcpy() it just to a packet, suggesting an
"on wire" representation.)

> +            av_log(avctx, AV_LOG_DEBUG, "rolling_shutter_skew_time = %lu\n",
> +                   rolling_shutter_skew_time);

These log calls inflate the code quite a lot. Consider dropping them,
and moving dumping the contents somewhere else. (Like ffprobe.)

> +            break;
> +        // float gyro[3]
> +        case 2:
> +            log_float_values(avctx, "gyro", (float*)camm_data);
> +            break;
> +        case 3:
> +            log_float_values(avctx, "acceleration", (float*)camm_data);
> +            break;
> +        // float position[3]
> +        case 4:
> +            log_float_values(avctx, "position", (float*)camm_data);
> +            break;
> +        // float latitude
> +        // float longitude
> +        // float altitude
> +        case 5:
> +            if (!validate_latitude(avctx, ((float*)camm_data)[0])) return 0;
> +            if (!validate_longitude(avctx, ((float*)camm_data)[1])) return 0;
> +
> +            av_log(avctx, AV_LOG_DEBUG, "latitude = %.6f\n",
> +                   ((float*)camm_data)[0]);
> +            av_log(avctx, AV_LOG_DEBUG, "longitude = %.6f\n",
> +                   ((float*)camm_data)[1]);
> +            av_log(avctx, AV_LOG_DEBUG, "altitude = %.6f\n",
> +                   ((float*)camm_data)[2]);
> +            break;
> +        case 6:
> +            time_gps_epoch = ((double*)camm_data)[0];
> +            if (time_gps_epoch < 0) {
> +                av_log(avctx, AV_LOG_ERROR,
> +                       "Time gps epoch %.6f is less than 0.\n",
> +                       time_gps_epoch);
> +                return 0;
> +            }
> +            av_log(avctx, AV_LOG_DEBUG, "time_gps_epoch = %.6f\n",
> +                   time_gps_epoch);
> +            camm_data = (uint32_t*) (((double*)camm_data) + 1);
> +
> +            gps_fix_type = ((uint32_t*)camm_data)[0];
> +            if (gps_fix_type != 0 && gps_fix_type != 1 && gps_fix_type != 2) 
> {
> +                av_log(avctx, AV_LOG_ERROR,
> +                       "GPS fix type %d is not valid. Should be 0, 1, or 
> 2\n",
> +                       gps_fix_type);
> +                return 0;
> +            }
> +            av_log(avctx, AV_LOG_DEBUG, "gps_fix_type = %d\n", gps_fix_type);
> +            camm_data = (uint32_t*) (((int32_t*)camm_data) + 1);
> +
> +            latitude = ((double*)camm_data)[0];
> +            if (!validate_latitude(avctx, latitude)) return 0;
> +            av_log(avctx, AV_LOG_DEBUG, "latitude = %.6f\n", latitude);
> +            camm_data = (uint32_t*) (((double*)camm_data) + 1);
> +
> +            longitude = ((double*)camm_data)[0];
> +            if (!validate_longitude(avctx, longitude)) return 0;
> +            av_log(avctx, AV_LOG_DEBUG, "longitude = %.6f\n", latitude);
> +            camm_data = (uint32_t*) (((double*)camm_data) + 1);
> +
> +            altitude = ((float*)camm_data)[0];
> +            av_log(avctx, AV_LOG_DEBUG, "altitude = %.6f\n", altitude);
> +            camm_data = (uint32_t*) (((float*)camm_data) + 1);
> +
> +            av_log(avctx, AV_LOG_DEBUG, "horizontal accuracy = %.6f\n",
> +                   ((float*)camm_data)[0]);
> +            camm_data = (uint32_t*) (((float*)camm_data) + 1);
> +
> +            av_log(avctx, AV_LOG_DEBUG, "vertical accuracy %.6f\n",
> +                   ((float*)camm_data)[0]);
> +            camm_data = (uint32_t*) (((float*)camm_data) + 1);
> +
> +            av_log(avctx, AV_LOG_DEBUG, "vertical east %.6f\n",
> +                   ((float*)camm_data)[0]);
> +            camm_data = (uint32_t*) (((float*)camm_data) + 1);
> +
> +            av_log(avctx, AV_LOG_DEBUG, "vertical north %.6f\n",
> +                   ((float*)camm_data)[0]);
> +            camm_data = (uint32_t*) (((float*)camm_data) + 1);
> +
> +            av_log(avctx, AV_LOG_DEBUG, "vertical up %.6f\n",
> +                   ((float*)camm_data)[0]);
> +            camm_data = (uint32_t*) (((float*)camm_data) + 1);
> +
> +            av_log(avctx, AV_LOG_DEBUG, "speed accuracy %.6f\n",
> +                   ((float*)camm_data)[0]);
> +            camm_data = (uint32_t*) (((float*)camm_data) + 1);
> +            break;
> +        // float magnetic_field[3]
> +        case 7:
> +            log_float_values(avctx, "magnetic_field", (float*)camm_data);
> +            break;
> +    }
> +
> +    return 1;
> +}
> +
> +/**
> + * Encode camera motion metadata. Essentially, this encoder validates the
> + * input data and then just copies the data to an output AVPacket.
> + *  @param avctx          The AVCodecContext context.
> + *  @param packet         The output packet to write the encoded data.
> + *  @param data           The input camera sensor data.
> + *  @param got_packet     1 if a non-empty packet was returned, 0 otherwise.
> + */
> +static int encode_data(AVCodecContext *avctx, AVPacket *packet,
> +                        const AVFrame *data, int *got_packet)
> +{
> +    int ret;
> +
> +    if (!validate_data(avctx, data)) {
> +        return AVERROR(EINVAL);
> +    }
> +
> +    // Make sure there is enough size allocated in packet->data.
> +    if ((ret = ff_alloc_packet2(avctx, packet, data->pkt_size, 0)) < 0) {
> +        av_log(avctx, AV_LOG_ERROR, "Can't allocate %d bytes in packet\n",
> +               data->pkt_size);
> +        return ret;
> +    }
> +
> +    // Copy necessary fields to the AVPacket.
> +    packet->pts = data->pts;
> +    packet->duration = data->pkt_duration;
> +    memcpy(packet->data, *(data->extended_data), data->pkt_size);

So why is this an encoder at all? What's the use? I suspect some
ffmpeg.c nonsense about just copying the data from a source file to a
destination file? But then you could probably use its codec copy path.

What is this encoder, which encodes nothing, supposed to be used for?

> +
> +    // Indicate that a packet was created.
> +    *got_packet = 1;
> +    return 0;
> +}
> +
> +/**
> + * Initializes the codec.
> + *
> + * @param avctx     The AVCodecContext context.
> + */
> +static av_cold int encode_init(AVCodecContext *avctx) {
> +    // Use dummy values for the height and width.
> +    avctx->width = DUMMY_ENCODER_SIZE;
> +    avctx->height = DUMMY_ENCODER_SIZE;
> +    avctx->max_pixels = DUMMY_ENCODER_SIZE;

What? This makes no sense.

> +
> +    return 0;
> +}
> +
> +// Define the encoder that ffmpeg will use for CAMM data.
> +AVCodec ff_camera_motion_metadata_encoder = {
> +    .name           = "camm",
> +    .long_name      = NULL_IF_CONFIG_SMALL("camera motion metadata"),
> +    .type           = AVMEDIA_TYPE_DATA,
> +    .id             = AV_CODEC_ID_CAMERA_MOTION_METADATA,
> +    .priv_data_size = sizeof(CammContext),
> +    .encode2        = encode_data,
> +    .init           = encode_init,
> +};
> diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
> index cf1246e431..014c1cd6b3 100644
> --- a/libavcodec/codec_desc.c
> +++ b/libavcodec/codec_desc.c
> @@ -3100,6 +3100,12 @@ static const AVCodecDescriptor codec_descriptors[] = {
>          .name      = "scte_35",
>          .long_name = NULL_IF_CONFIG_SMALL("SCTE 35 Message Queue"),
>      },
> +    {
> +        .id        = AV_CODEC_ID_CAMERA_MOTION_METADATA,
> +        .type      = AVMEDIA_TYPE_DATA,
> +        .name      = "camm",
> +        .long_name = NULL_IF_CONFIG_SMALL("camera motion metadata"),
> +    },
>  
>      /* deprecated codec ids */
>  };
> diff --git a/libavcodec/version.h b/libavcodec/version.h
> index 3c5fea9327..5b99785a72 100644
> --- a/libavcodec/version.h
> +++ b/libavcodec/version.h
> @@ -28,8 +28,8 @@
>  #include "libavutil/version.h"
>  
>  #define LIBAVCODEC_VERSION_MAJOR  57
> -#define LIBAVCODEC_VERSION_MINOR 100
> -#define LIBAVCODEC_VERSION_MICRO 103
> +#define LIBAVCODEC_VERSION_MINOR 101
> +#define LIBAVCODEC_VERSION_MICRO 100
>  
>  #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
>                                                 LIBAVCODEC_VERSION_MINOR, \
> diff --git a/libavformat/isom.c b/libavformat/isom.c
> index 3a9b3baf96..ca5107bf7f 100644
> --- a/libavformat/isom.c
> +++ b/libavformat/isom.c
> @@ -67,6 +67,7 @@ const AVCodecTag ff_mp4_obj_type[] = {
>      { AV_CODEC_ID_VORBIS      , 0xDD }, /* nonstandard, gpac uses it */
>      { AV_CODEC_ID_DVD_SUBTITLE, 0xE0 }, /* nonstandard, see 
> unsupported-embedded-subs-2.mp4 */
>      { AV_CODEC_ID_QCELP       , 0xE1 },
> +    { AV_CODEC_ID_CAMERA_MOTION_METADATA, 0xE2 },
>      { AV_CODEC_ID_MPEG4SYSTEMS, 0x01 },
>      { AV_CODEC_ID_MPEG4SYSTEMS, 0x02 },
>      { AV_CODEC_ID_NONE        ,    0 },
> @@ -368,6 +369,11 @@ const AVCodecTag ff_codec_movsubtitle_tags[] = {
>      { AV_CODEC_ID_NONE, 0 },
>  };
>  
> +const AVCodecTag ff_codec_movdata_tags[] = {
> +    { AV_CODEC_ID_CAMERA_MOTION_METADATA, MKTAG('c','a','m','m') },
> +};
> +
> +
>  /* map numeric codes from mdhd atom to ISO 639 */
>  /* cf. QTFileFormat.pdf p253, qtff.pdf p205 */
>  /* http://developer.apple.com/documentation/mac/Text/Text-368.html */
> diff --git a/libavformat/movenc.c b/libavformat/movenc.c
> index 88f2f2c819..49528f8635 100644
> --- a/libavformat/movenc.c
> +++ b/libavformat/movenc.c
> @@ -35,8 +35,6 @@
>  #include "libavcodec/dnxhddata.h"
>  #include "libavcodec/flac.h"
>  #include "libavcodec/get_bits.h"
> -
> -#include "libavcodec/internal.h"
>  #include "libavcodec/put_bits.h"
>  #include "libavcodec/vc1_common.h"
>  #include "libavcodec/raw.h"
> @@ -1126,10 +1124,7 @@ static int mov_write_hvcc_tag(AVIOContext *pb, 
> MOVTrack *track)
>  
>      avio_wb32(pb, 0);
>      ffio_wfourcc(pb, "hvcC");
> -    if (track->tag == MKTAG('h','v','c','1'))
> -        ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 1);
> -    else
> -        ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 0);
> +    ff_isom_write_hvcc(pb, track->vos_data, track->vos_len, 0);
>      return update_size(pb, pos);
>  }
>  
> @@ -1230,6 +1225,60 @@ static int mov_write_dpxe_tag(AVIOContext *pb, 
> MOVTrack *track)
>      return 0;
>  }
>  
> +static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track)
> +{
> +    int tag = track->par->codec_tag;
> +
> +    if (!ff_codec_get_tag(ff_mp4_obj_type, track->par->codec_id))
> +        return 0;
> +
> +    if      (track->par->codec_id == AV_CODEC_ID_H264)      tag = 
> MKTAG('a','v','c','1');
> +    else if (track->par->codec_id == AV_CODEC_ID_HEVC)      tag = 
> MKTAG('h','e','v','1');
> +    else if (track->par->codec_id == AV_CODEC_ID_VP9)       tag = 
> MKTAG('v','p','0','9');
> +    else if (track->par->codec_id == AV_CODEC_ID_AC3)       tag = 
> MKTAG('a','c','-','3');
> +    else if (track->par->codec_id == AV_CODEC_ID_EAC3)      tag = 
> MKTAG('e','c','-','3');
> +    else if (track->par->codec_id == AV_CODEC_ID_DIRAC)     tag = 
> MKTAG('d','r','a','c');
> +    else if (track->par->codec_id == AV_CODEC_ID_MOV_TEXT)  tag = 
> MKTAG('t','x','3','g');
> +    else if (track->par->codec_id == AV_CODEC_ID_VC1)       tag = 
> MKTAG('v','c','-','1');
> +    else if (track->par->codec_id == AV_CODEC_ID_FLAC)      tag = 
> MKTAG('f','L','a','C');
> +    else if (track->par->codec_id == AV_CODEC_ID_OPUS)      tag = 
> MKTAG('O','p','u','s');
> +    else if (track->par->codec_type == AVMEDIA_TYPE_VIDEO)  tag = 
> MKTAG('m','p','4','v');
> +    else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO)  tag = 
> MKTAG('m','p','4','a');
> +    else if (track->par->codec_id == AV_CODEC_ID_DVD_SUBTITLE)  tag = 
> MKTAG('m','p','4','s');
> +
> +    return tag;
> +}
> +
> +static const AVCodecTag codec_ipod_tags[] = {
> +    { AV_CODEC_ID_H264,     MKTAG('a','v','c','1') },
> +    { AV_CODEC_ID_MPEG4,    MKTAG('m','p','4','v') },
> +    { AV_CODEC_ID_AAC,      MKTAG('m','p','4','a') },
> +    { AV_CODEC_ID_ALAC,     MKTAG('a','l','a','c') },
> +    { AV_CODEC_ID_AC3,      MKTAG('a','c','-','3') },
> +    { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
> +    { AV_CODEC_ID_MOV_TEXT, MKTAG('t','e','x','t') },
> +    { AV_CODEC_ID_NONE, 0 },
> +};
> +
> +static int ipod_get_codec_tag(AVFormatContext *s, MOVTrack *track)
> +{
> +    int tag = track->par->codec_tag;
> +
> +    // keep original tag for subs, ipod supports both formats
> +    if (!(track->par->codec_type == AVMEDIA_TYPE_SUBTITLE &&
> +          (tag == MKTAG('t', 'x', '3', 'g') ||
> +           tag == MKTAG('t', 'e', 'x', 't'))))
> +        tag = ff_codec_get_tag(codec_ipod_tags, track->par->codec_id);
> +
> +    if (!av_match_ext(s->filename, "m4a") &&
> +        !av_match_ext(s->filename, "m4b") &&
> +        !av_match_ext(s->filename, "m4v"))
> +        av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a, .m4v nor  
> .m4b "
> +               "Quicktime/Ipod might not play the file\n");
> +
> +    return tag;
> +}
> +
>  static int mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track)
>  {
>      int tag;
> @@ -1506,25 +1555,42 @@ static int mov_get_codec_tag(AVFormatContext *s, 
> MOVTrack *track)
>      return tag;
>  }
>  
> +static const AVCodecTag codec_3gp_tags[] = {
> +    { AV_CODEC_ID_H263,     MKTAG('s','2','6','3') },
> +    { AV_CODEC_ID_H264,     MKTAG('a','v','c','1') },
> +    { AV_CODEC_ID_MPEG4,    MKTAG('m','p','4','v') },
> +    { AV_CODEC_ID_AAC,      MKTAG('m','p','4','a') },
> +    { AV_CODEC_ID_AMR_NB,   MKTAG('s','a','m','r') },
> +    { AV_CODEC_ID_AMR_WB,   MKTAG('s','a','w','b') },
> +    { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
> +    { AV_CODEC_ID_NONE, 0 },
> +};
> +
> +static const AVCodecTag codec_f4v_tags[] = { // XXX: add GIF/PNG/JPEG?
> +    { AV_CODEC_ID_MP3,    MKTAG('.','m','p','3') },
> +    { AV_CODEC_ID_AAC,    MKTAG('m','p','4','a') },
> +    { AV_CODEC_ID_H264,   MKTAG('a','v','c','1') },
> +    { AV_CODEC_ID_VP6A,   MKTAG('V','P','6','A') },
> +    { AV_CODEC_ID_VP6F,   MKTAG('V','P','6','F') },
> +    { AV_CODEC_ID_NONE, 0 },
> +};
> +
>  static int mov_find_codec_tag(AVFormatContext *s, MOVTrack *track)
>  {
>      int tag;
>  
>      if (track->mode == MODE_MP4 || track->mode == MODE_PSP)
> -        tag = track->par->codec_tag;
> -    else if (track->mode == MODE_ISM)
> -        tag = track->par->codec_tag;
> -    else if (track->mode == MODE_IPOD) {
> -        if (!av_match_ext(s->filename, "m4a") &&
> -            !av_match_ext(s->filename, "m4v") &&
> -            !av_match_ext(s->filename, "m4b"))
> -            av_log(s, AV_LOG_WARNING, "Warning, extension is not .m4a nor 
> .m4v "
> -                   "Quicktime/Ipod might not play the file\n");
> -        tag = track->par->codec_tag;
> -    } else if (track->mode & MODE_3GP)
> -        tag = track->par->codec_tag;
> +        tag = mp4_get_codec_tag(s, track);
> +    else if (track->mode == MODE_ISM) {
> +        tag = mp4_get_codec_tag(s, track);
> +        if (!tag && track->par->codec_id == AV_CODEC_ID_WMAPRO)
> +            tag = MKTAG('w', 'm', 'a', ' ');
> +    } else if (track->mode == MODE_IPOD)
> +        tag = ipod_get_codec_tag(s, track);
> +    else if (track->mode & MODE_3GP)
> +        tag = ff_codec_get_tag(codec_3gp_tags, track->par->codec_id);
>      else if (track->mode == MODE_F4V)
> -        tag = track->par->codec_tag;
> +        tag = ff_codec_get_tag(codec_f4v_tags, track->par->codec_id);
>      else
>          tag = mov_get_codec_tag(s, track);
>  
> @@ -2060,6 +2126,19 @@ static int mov_write_tmcd_tag(AVIOContext *pb, 
> MOVTrack *track)
>      return update_size(pb, pos);
>  }
>  
> +static int mov_write_camm_tag(AVIOContext *pb) {
> +    int64_t size_update;
> +    int64_t pos = avio_tell(pb);
> +    avio_wb32(pb, 0); /* size */
> +    ffio_wfourcc(pb, "camm");
> +    avio_wb32(pb, 0); /* Reserved */
> +    avio_wb16(pb, 0); /* Reserved */
> +    avio_wb16(pb, 1); /* Data-reference index */
> +
> +    size_update = update_size(pb, pos);
> +    return size_update;
> +}
> +
>  static int mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, 
> MOVMuxContext *mov, MOVTrack *track)
>  {
>      int64_t pos = avio_tell(pb);
> @@ -2077,6 +2156,10 @@ static int mov_write_stsd_tag(AVFormatContext *s, 
> AVIOContext *pb, MOVMuxContext
>          mov_write_rtp_tag(pb, track);
>      else if (track->par->codec_tag == MKTAG('t','m','c','d'))
>          mov_write_tmcd_tag(pb, track);
> +    else if (track->par->codec_tag
> +             == ff_codec_get_tag(ff_mp4_obj_type,
> +                                 AV_CODEC_ID_CAMERA_MOTION_METADATA))
> +        mov_write_camm_tag(pb);
>      return update_size(pb, pos);
>  }
>  
> @@ -2443,6 +2526,11 @@ static int mov_write_hdlr_tag(AVFormatContext *s, 
> AVIOContext *pb, MOVTrack *tra
>          } else if (track->par->codec_tag == MKTAG('t','m','c','d')) {
>              hdlr_type = "tmcd";
>              descr = "TimeCodeHandler";
> +        } else if (track->par->codec_tag
> +                       == ff_codec_get_tag(ff_mp4_obj_type,
> +                            AV_CODEC_ID_CAMERA_MOTION_METADATA)) {
> +            hdlr_type = "camm";
> +            descr = "CameraMetadataMotionHandler";
>          } else {
>              av_log(s, AV_LOG_WARNING,
>                     "Unknown hldr_type for %s, writing dummy values\n",
> @@ -6422,73 +6510,6 @@ static int mov_check_bitstream(struct AVFormatContext 
> *s, const AVPacket *pkt)
>      return ret;
>  }
>  
> -static const AVCodecTag codec_3gp_tags[] = {
> -    { AV_CODEC_ID_H263,     MKTAG('s','2','6','3') },
> -    { AV_CODEC_ID_H264,     MKTAG('a','v','c','1') },
> -    { AV_CODEC_ID_MPEG4,    MKTAG('m','p','4','v') },
> -    { AV_CODEC_ID_AAC,      MKTAG('m','p','4','a') },
> -    { AV_CODEC_ID_AMR_NB,   MKTAG('s','a','m','r') },
> -    { AV_CODEC_ID_AMR_WB,   MKTAG('s','a','w','b') },
> -    { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
> -    { AV_CODEC_ID_NONE, 0 },
> -};
> -
> -const AVCodecTag codec_mp4_tags[] = {
> -    { AV_CODEC_ID_MPEG4       , MKTAG('m', 'p', '4', 'v') },
> -    { AV_CODEC_ID_H264        , MKTAG('a', 'v', 'c', '1') },
> -    { AV_CODEC_ID_HEVC        , MKTAG('h', 'e', 'v', '1') },
> -    { AV_CODEC_ID_HEVC        , MKTAG('h', 'v', 'c', '1') },
> -    { AV_CODEC_ID_MPEG2VIDEO  , MKTAG('m', 'p', '4', 'v') },
> -    { AV_CODEC_ID_MPEG1VIDEO  , MKTAG('m', 'p', '4', 'v') },
> -    { AV_CODEC_ID_MJPEG       , MKTAG('m', 'p', '4', 'v') },
> -    { AV_CODEC_ID_PNG         , MKTAG('m', 'p', '4', 'v') },
> -    { AV_CODEC_ID_JPEG2000    , MKTAG('m', 'p', '4', 'v') },
> -    { AV_CODEC_ID_VC1         , MKTAG('v', 'c', '-', '1') },
> -    { AV_CODEC_ID_DIRAC       , MKTAG('d', 'r', 'a', 'c') },
> -    { AV_CODEC_ID_TSCC2       , MKTAG('m', 'p', '4', 'v') },
> -    { AV_CODEC_ID_VP9         , MKTAG('v', 'p', '0', '9') },
> -    { AV_CODEC_ID_AAC         , MKTAG('m', 'p', '4', 'a') },
> -    { AV_CODEC_ID_MP4ALS      , MKTAG('m', 'p', '4', 'a') },
> -    { AV_CODEC_ID_MP3         , MKTAG('m', 'p', '4', 'a') },
> -    { AV_CODEC_ID_MP2         , MKTAG('m', 'p', '4', 'a') },
> -    { AV_CODEC_ID_AC3         , MKTAG('a', 'c', '-', '3') },
> -    { AV_CODEC_ID_EAC3        , MKTAG('e', 'c', '-', '3') },
> -    { AV_CODEC_ID_DTS         , MKTAG('m', 'p', '4', 'a') },
> -    { AV_CODEC_ID_FLAC        , MKTAG('f', 'L', 'a', 'C') },
> -    { AV_CODEC_ID_OPUS        , MKTAG('O', 'p', 'u', 's') },
> -    { AV_CODEC_ID_VORBIS      , MKTAG('m', 'p', '4', 'a') },
> -    { AV_CODEC_ID_QCELP       , MKTAG('m', 'p', '4', 'a') },
> -    { AV_CODEC_ID_EVRC        , MKTAG('m', 'p', '4', 'a') },
> -    { AV_CODEC_ID_DVD_SUBTITLE, MKTAG('m', 'p', '4', 's') },
> -    { AV_CODEC_ID_MOV_TEXT    , MKTAG('t', 'x', '3', 'g') },
> -    { AV_CODEC_ID_NONE        ,    0 },
> -};
> -
> -const AVCodecTag codec_ism_tags[] = {
> -    { AV_CODEC_ID_WMAPRO      , MKTAG('w', 'm', 'a', ' ') },
> -    { AV_CODEC_ID_NONE        ,    0 },
> -};
> -
> -static const AVCodecTag codec_ipod_tags[] = {
> -    { AV_CODEC_ID_H264,     MKTAG('a','v','c','1') },
> -    { AV_CODEC_ID_MPEG4,    MKTAG('m','p','4','v') },
> -    { AV_CODEC_ID_AAC,      MKTAG('m','p','4','a') },
> -    { AV_CODEC_ID_ALAC,     MKTAG('a','l','a','c') },
> -    { AV_CODEC_ID_AC3,      MKTAG('a','c','-','3') },
> -    { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') },
> -    { AV_CODEC_ID_MOV_TEXT, MKTAG('t','e','x','t') },
> -    { AV_CODEC_ID_NONE, 0 },
> -};
> -
> -static const AVCodecTag codec_f4v_tags[] = {
> -    { AV_CODEC_ID_MP3,    MKTAG('.','m','p','3') },
> -    { AV_CODEC_ID_AAC,    MKTAG('m','p','4','a') },
> -    { AV_CODEC_ID_H264,   MKTAG('a','v','c','1') },
> -    { AV_CODEC_ID_VP6A,   MKTAG('V','P','6','A') },
> -    { AV_CODEC_ID_VP6F,   MKTAG('V','P','6','F') },
> -    { AV_CODEC_ID_NONE, 0 },
> -};
> -
>  #if CONFIG_MOV_MUXER
>  MOV_CLASS(mov)
>  AVOutputFormat ff_mov_muxer = {
> @@ -6549,7 +6570,7 @@ AVOutputFormat ff_mp4_muxer = {
>      .write_trailer     = mov_write_trailer,
>      .deinit            = mov_free,
>      .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | 
> AVFMT_TS_NEGATIVE,
> -    .codec_tag         = (const AVCodecTag* const []){ codec_mp4_tags, 0 },
> +    .codec_tag         = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 },
>      .check_bitstream   = mov_check_bitstream,
>      .priv_class        = &mp4_muxer_class,
>  };
> @@ -6570,7 +6591,7 @@ AVOutputFormat ff_psp_muxer = {
>      .write_trailer     = mov_write_trailer,
>      .deinit            = mov_free,
>      .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | 
> AVFMT_TS_NEGATIVE,
> -    .codec_tag         = (const AVCodecTag* const []){ codec_mp4_tags, 0 },
> +    .codec_tag         = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 },
>      .check_bitstream   = mov_check_bitstream,
>      .priv_class        = &psp_muxer_class,
>  };
> @@ -6632,8 +6653,7 @@ AVOutputFormat ff_ismv_muxer = {
>      .write_trailer     = mov_write_trailer,
>      .deinit            = mov_free,
>      .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | 
> AVFMT_TS_NEGATIVE,
> -    .codec_tag         = (const AVCodecTag* const []){
> -        codec_mp4_tags, codec_ism_tags, 0 },
> +    .codec_tag         = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 },
>      .check_bitstream   = mov_check_bitstream,
>      .priv_class        = &ismv_muxer_class,
>  };

This stuff apparently got in by mistake?

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to