Quoting Vittorio Giovara (2016-11-01 20:23:35) > This includes both versions of the spec, XML and mp4 box. > > Signed-off-by: Vittorio Giovara <vittorio.giov...@gmail.com> > --- > avprobe.c | 20 ++++ > libavcodec/avcodec.h | 44 ++++++++ > libavformat/dump.c | 28 ++++++ > libavformat/isom.h | 4 + > libavformat/mov.c | 277 > +++++++++++++++++++++++++++++++++++++++++++++++++++ > 5 files changed, 373 insertions(+) > > diff --git a/avprobe.c b/avprobe.c > index eff9c0d..474b325 100644 > --- a/avprobe.c > +++ b/avprobe.c > @@ -729,6 +729,7 @@ static void show_stream(InputFile *ifile, InputStream > *ist) > for (i = 0; i < stream->nb_side_data; i++) { > const AVPacketSideData* sd = &stream->side_data[i]; > AVStereo3D *stereo; > + AVSphericalVideo *spherical; > > switch (sd->type) { > case AV_PKT_DATA_DISPLAYMATRIX: > @@ -749,6 +750,25 @@ static void show_stream(InputFile *ifile, InputStream > *ist) > !!(stereo->flags & AV_STEREO3D_FLAG_INVERT)); > probe_object_footer("stereo3d"); > break; > + case AV_PKT_DATA_SPHERICAL: > + spherical = (AVSphericalVideo *)sd->data; > + probe_object_header("spherical"); > + > + if (spherical->type == AV_SPHERICAL_EQUIRECTANGULAR) > + probe_str("projection", "equirectangular"); > + else if (spherical->type == AV_SPHERICAL_CUBEMAP) > + probe_str("projection", "cubemap"); > + else if (spherical->type == AV_SPHERICAL_MESH) > + probe_str("projection", "mesh"); > + else > + probe_str("projection", "unknown"); > + > + probe_int("yaw", spherical->yaw); > + probe_int("pitch", spherical->pitch); > + probe_int("roll", spherical->roll); > + > + probe_object_footer("spherical"); > + break; > } > } > probe_object_footer("sidedata"); > diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h > index 88e6c62..c301977 100644 > --- a/libavcodec/avcodec.h > +++ b/libavcodec/avcodec.h > @@ -702,6 +702,44 @@ enum AVAudioServiceType { > AV_AUDIO_SERVICE_TYPE_NB , ///< Not part of ABI > }; > > +/** > + * Video surface should be mapped on a sphere, and probably needs additional > + * processing before it can be displayed. > + */ > +enum AVSphericalType { > + AV_SPHERICAL_EQUIRECTANGULAR, > + AV_SPHERICAL_CUBEMAP, > + AV_SPHERICAL_MESH, > + AV_SPHERICAL_NB, ///< Not part of ABI
-ENEEDMOREDOCS > +}; > + > +/** > + * @note Size of this struct is not part of ABI. > + */ > +typedef struct AVSphericalVideo { This needs a constructor. Cf. e.g. to the av_cpb_* API. > +static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom) > +{ > + AVStream *st; > + MOVStreamContext *sc; > + int ret; > + > + uint8_t uuid[16]; > + static const uint8_t uuid_spherical[] = { > + 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93, > + 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd, > + }; > + > + if (atom.size < sizeof(uuid) || atom.size == INT64_MAX) > + return AVERROR_INVALIDDATA; > + > + if (c->fc->nb_streams < 1) > + return 0; > + st = c->fc->streams[c->fc->nb_streams - 1]; > + sc = st->priv_data; > + > + ret = ffio_read_size(pb, uuid, sizeof(uuid)); > + if (ret < 0) > + return ret; > + > + if (!memcmp(uuid, uuid_spherical, sizeof(uuid)) && !sc->spherical) { > + size_t len = atom.size - sizeof(uuid); > + ret = mov_parse_uuid_spherical(sc, pb, len); > + if (ret < 0) > + return ret; > + if (!sc->spherical) > + av_log(c->fc, AV_LOG_WARNING, "Invalid spherical metadata > found\n"); > + } else { > + int i; > + av_log(c->fc, AV_LOG_WARNING, "Unknown UUID found: 0x"); Should this be a warning? It's just some unknown data we can safely ignore, no? So verbose or debug. > + for (i = 0; i < sizeof(uuid); i++) > + av_log(c->fc, AV_LOG_WARNING, "%02x", uuid[i]); > + av_log(c->fc, AV_LOG_WARNING, "\n"); > + } > + > + return 0; > +} > + > static const MOVParseTableEntry mov_default_parse_table[] = { > { MKTAG('a','v','s','s'), mov_read_extradata }, > { MKTAG('c','h','p','l'), mov_read_chpl }, > @@ -3217,6 +3454,9 @@ static const MOVParseTableEntry > mov_default_parse_table[] = { > { MKTAG('d','v','c','1'), mov_read_dvc1 }, > { MKTAG('s','b','g','p'), mov_read_sbgp }, > { MKTAG('h','v','c','C'), mov_read_glbl }, > +{ MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */ > +{ MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */ > +{ MKTAG('u','u','i','d'), mov_read_uuid }, /* universal unique identifier */ > { MKTAG('-','-','-','-'), mov_read_custom }, > { 0, NULL } > }; > @@ -3445,6 +3685,9 @@ static int mov_read_close(AVFormatContext *s) > av_free(sc->extradata[j]); > av_freep(&sc->extradata); > av_freep(&sc->extradata_size); > + > + av_freep(&sc->spherical); > + av_freep(&sc->stereo3d); > } > > if (mov->dv_demux) { > @@ -3543,6 +3786,40 @@ static int mov_read_header(AVFormatContext *s) > sd->data = (uint8_t*)sc->display_matrix; > sc->display_matrix = NULL; > } > + if (sc->spherical) { > + AVPacketSideData *sd, *tmp; > + > + tmp = av_realloc_array(st->side_data, > + st->nb_side_data + 1, sizeof(*tmp)); > + if (!tmp) > + return AVERROR(ENOMEM); > + > + st->side_data = tmp; > + st->nb_side_data++; > + > + sd = &st->side_data[st->nb_side_data - 1]; > + sd->type = AV_PKT_DATA_SPHERICAL; > + sd->size = sizeof(*sc->spherical); > + sd->data = (uint8_t *)sc->spherical; > + sc->spherical = NULL; > + } > + if (sc->stereo3d) { > + AVPacketSideData *sd, *tmp; > + > + tmp = av_realloc_array(st->side_data, > + st->nb_side_data + 1, sizeof(*tmp)); > + if (!tmp) > + return AVERROR(ENOMEM); > + > + st->side_data = tmp; > + st->nb_side_data++; > + > + sd = &st->side_data[st->nb_side_data - 1]; > + sd->type = AV_PKT_DATA_STEREO3D; > + sd->size = sizeof(*sc->stereo3d); > + sd->data = (uint8_t *)sc->stereo3d; > + sc->stereo3d = NULL; > + } nit: the three if() blocks here are pretty much identical, might be nice to de-duplicate them a bit. Also, missing apichanges+bump. And I'd split the part adding the new API and actually making use of it. -- Anton Khirnov _______________________________________________ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel