diff -ur libav-v10.1.orig/libavcodec/avcodec.h libav-v10.1/libavcodec/avcodec.h --- libav-v10.1.orig/libavcodec/avcodec.h 2014-05-10 10:03:46.000000000 -0600 +++ libav-v10.1/libavcodec/avcodec.h 2016-01-03 11:08:50.502675261 -0700 @@ -923,8 +923,22 @@ * @endcode */ AV_PKT_DATA_H263_MB_INFO, + + /** + * This side data contains an integer value representing the stream index + * of a "fallback" track. A fallback track indicates an alternate + * track to use when the current track can not be decoded for some reason. + * e.g. no decoder available for codec. + */ + AV_PKT_DATA_FALLBACK_TRACK, }; +typedef struct AVPacketSideData { + uint8_t *data; + int size; + enum AVPacketSideDataType type; +} AVPacketSideData; + /** * This structure stores compressed data. It is typically exported by demuxers * and then passed as input to decoders, or received as output from encoders and @@ -981,11 +995,7 @@ * Additional packet data that can be provided by the container. * Packet can contain several types of side information. */ - struct { - uint8_t *data; - int size; - enum AVPacketSideDataType type; - } *side_data; + AVPacketSideData *side_data; int side_data_elems; /** diff -ur libav-v10.1.orig/libavformat/avformat.h libav-v10.1/libavformat/avformat.h --- libav-v10.1.orig/libavformat/avformat.h 2014-05-10 10:03:46.000000000 -0600 +++ libav-v10.1/libavformat/avformat.h 2016-01-03 10:55:46.558170954 -0700 @@ -755,6 +755,28 @@ */ AVPacket attached_pic; + /** + * An array of side data that applies to the whole stream (i.e. the + * container does not allow it to change between packets). + * + * There may be no overlap between the side data in this array and side data + * in the packets. I.e. a given side data is either exported by the muxer + * (demuxing) / set by the caller (muxing) in this array, then it never + * appears in the packets, or the side data is exported / sent through + * the packets (always in the first packet where the value becomes known or + * changes), then it does not appear in this array. + * + * - demuxing: Set by libavformat when the stream is created. + * - muxing: May be set by the caller before avformat_write_header(). + * + * Freed by libavformat in avformat_free_context(). + */ + AVPacketSideData *side_data; + /** + * The number of elements in the AVStream.side_data array. + */ + int nb_side_data; + /***************************************************************** * All fields below this line are not part of the public API. They * may not be used outside of libavformat and can be changed and @@ -1307,6 +1329,29 @@ AVInputFormat *av_probe_input_format(AVProbeData *pd, int is_opened); /** + * Allocate new information from stream. + * + * @param stream stream + * @param type desired side information type + * @param size side information size + * @return pointer to fresh allocated data or NULL otherwise + */ +uint8_t *av_stream_new_side_data(AVStream *stream, + enum AVPacketSideDataType type, int size); + +/** + * Get side information from stream. + * + * @param stream stream + * @param type desired side information type + * @param size pointer for side information size to store (optional) + * @return pointer to data if present or NULL otherwise + */ +uint8_t *av_stream_get_side_data(AVStream *stream, + enum AVPacketSideDataType type, int *size); + + +/** * Guess the file format. * * @param pd data to be probed diff -ur libav-v10.1.orig/libavformat/movenc.c libav-v10.1/libavformat/movenc.c --- libav-v10.1.orig/libavformat/movenc.c 2014-05-10 10:03:46.000000000 -0600 +++ libav-v10.1/libavformat/movenc.c 2016-01-03 11:25:26.833901308 -0700 @@ -2106,10 +2106,21 @@ mov->tracks[i].tref_id = mov->tracks[mov->chapter_track].track_id; } for (i = 0; i < mov->nb_streams; i++) { - if (mov->tracks[i].tag == MKTAG('r','t','p',' ')) { - mov->tracks[i].tref_tag = MKTAG('h','i','n','t'); - mov->tracks[i].tref_id = - mov->tracks[mov->tracks[i].src_track].track_id; + MOVTrack *track = &mov->tracks[i]; + 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->enc->codec_type == AVMEDIA_TYPE_AUDIO) { + int * fallback, size; + fallback = (int*)av_stream_get_side_data(track->st, + AV_PKT_DATA_FALLBACK_TRACK, + &size); + if (fallback != NULL && size == sizeof(int)) { + if (*fallback >= 0 && *fallback < mov->nb_streams) { + track->tref_tag = MKTAG('f','a','l','l'); + track->tref_id = mov->tracks[*fallback].track_id; + } + } } } diff -ur libav-v10.1.orig/libavformat/utils.c libav-v10.1/libavformat/utils.c --- libav-v10.1.orig/libavformat/utils.c 2014-05-10 10:03:46.000000000 -0600 +++ libav-v10.1/libavformat/utils.c 2016-01-03 11:03:50.830126004 -0700 @@ -2592,6 +2592,36 @@ return AVERROR(ENOSYS); } +static void free_stream(AVStream **pst) +{ + AVStream *st = *pst; + int i; + + if (!st) + return; + + for (i = 0; i < st->nb_side_data; i++) + av_freep(&st->side_data[i].data); + av_freep(&st->side_data); + + if (st->parser) + av_parser_close(st->parser); + + if (st->attached_pic.data) + av_free_packet(&st->attached_pic); + + av_dict_free(&st->metadata); + av_freep(&st->probe_data.buf); + av_free(st->index_entries); + av_free(st->codec->extradata); + av_free(st->codec->subtitle_header); + av_free(st->codec); + av_free(st->priv_data); + av_free(st->info); + + av_freep(pst); +} + void avformat_free_context(AVFormatContext *s) { int i; @@ -2603,21 +2633,7 @@ for (i = 0; i < s->nb_streams; i++) { /* free all data in a stream component */ - st = s->streams[i]; - if (st->parser) { - av_parser_close(st->parser); - } - if (st->attached_pic.data) - av_free_packet(&st->attached_pic); - av_dict_free(&st->metadata); - av_freep(&st->probe_data.buf); - av_free(st->index_entries); - av_free(st->codec->extradata); - av_free(st->codec->subtitle_header); - av_free(st->codec); - av_free(st->priv_data); - av_free(st->info); - av_free(st); + free_stream(&s->streams[i]); } for (i = s->nb_programs - 1; i >= 0; i--) { av_dict_free(&s->programs[i]->metadata); @@ -3490,3 +3506,56 @@ return 0; } + +uint8_t *av_stream_get_side_data(AVStream *st, enum AVPacketSideDataType type, + int *size) +{ + int i; + + for (i = 0; i < st->nb_side_data; i++) { + if (st->side_data[i].type == type) { + if (size) + *size = st->side_data[i].size; + return st->side_data[i].data; + } + } + return NULL; +} + +uint8_t *av_stream_new_side_data(AVStream *st, enum AVPacketSideDataType type, + int size) +{ + AVPacketSideData *sd, *tmp; + int i; + uint8_t *data = av_malloc(size); + + if (!data) + return NULL; + + for (i = 0; i < st->nb_side_data; i++) { + sd = &st->side_data[i]; + + if (sd->type == type) { + av_freep(&sd->data); + sd->data = data; + sd->size = size; + return sd->data; + } + } + + tmp = av_realloc_array(st->side_data, st->nb_side_data + 1, sizeof(*tmp)); + if (!tmp) { + av_freep(&data); + return NULL; + } + + st->side_data = tmp; + st->nb_side_data++; + + sd = &st->side_data[st->nb_side_data - 1]; + sd->type = type; + sd->data = data; + sd->size = size; + return data; +} +