static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom)

{

    AVStream *st;

    MOVStreamContext *sc;

    int entries, i, j;



    if (c->fc->nb_streams < 1)

        return 0;

    st = c->fc->streams[c->fc->nb_streams-1];

    sc = st->priv_data;



    avio_rb32(pb); // version + flags

    entries = avio_rb32(pb);

    if (entries >  (atom.size - 1) / MIN_DATA_ENTRY_BOX_SIZE + 1 ||

        entries >= UINT_MAX / sizeof(*sc->drefs))

        return AVERROR_INVALIDDATA;

    av_free(sc->drefs);

    sc->drefs_count = 0;

    sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));

    if (!sc->drefs)

        return AVERROR(ENOMEM);

    sc->drefs_count = entries;



    for (i = 0; i < sc->drefs_count; i++) {

        MOVDref *dref = &sc->drefs[i];

        uint32_t size = avio_rb32(pb);

        int64_t next = avio_tell(pb) + size - 4;



        if (size < 12)

            return AVERROR_INVALIDDATA;



        dref->type = avio_rl32(pb);

        avio_rb32(pb); // version + flags

        av_dlog(c->fc, "type %.4s size %d\n", (char*)&dref->type, size);



        if (dref->type == MKTAG('a','l','i','s') && size > 150) {

            /* macintosh alias record */

            uint16_t volume_len, len;

            int16_t type;



            avio_skip(pb, 10);



            volume_len = avio_r8(pb);

            volume_len = FFMIN(volume_len, 27);

            avio_read(pb, dref->volume, 27);

            dref->volume[volume_len] = 0;

            av_log(c->fc, AV_LOG_DEBUG, "volume %s, len %d\n", dref->volume, volume_len);



            avio_skip(pb, 12);



            len = avio_r8(pb);

            len = FFMIN(len, 63);

            avio_read(pb, dref->filename, 63);

            dref->filename[len] = 0;

            av_log(c->fc, AV_LOG_DEBUG, "filename %s, len %d\n", dref->filename, len);



            avio_skip(pb, 16);



            /* read next level up_from_alias/down_to_target */

            dref->nlvl_from = avio_rb16(pb);

            dref->nlvl_to   = avio_rb16(pb);

            av_log(c->fc, AV_LOG_DEBUG, "nlvl from %d, nlvl to %d\n",

                   dref->nlvl_from, dref->nlvl_to);



            avio_skip(pb, 16);



            for (type = 0; type != -1 && avio_tell(pb) < next; ) {

                if(url_feof(pb))

                    return AVERROR_EOF;

                type = avio_rb16(pb);

                len = avio_rb16(pb);

                av_log(c->fc, AV_LOG_DEBUG, "type %d, len %d\n", type, len);

                if (len&1)

                    len += 1;

                if (type == 2) { // absolute path

                    av_free(dref->path);

                    dref->path = av_mallocz(len+1);

                    if (!dref->path)

                        return AVERROR(ENOMEM);

                    avio_read(pb, dref->path, len);

                    if (len > volume_len && !strncmp(dref->path, dref->volume, volume_len)) {

                        len -= volume_len;

                        memmove(dref->path, dref->path+volume_len, len);

                        dref->path[len] = 0;

                    }

                    for (j = 0; j < len; j++)

                        if (dref->path[j] == ':')

                            dref->path[j] = '/';

                    av_log(c->fc, AV_LOG_DEBUG, "path %s\n", dref->path);

                } else if (type == 0) { // directory name

                    av_free(dref->dir);

                    dref->dir = av_malloc(len+1);

                    if (!dref->dir)

                        return AVERROR(ENOMEM);

                    avio_read(pb, dref->dir, len);

                    dref->dir[len] = 0;

                    for (j = 0; j < len; j++)

                        if (dref->dir[j] == ':')

                            dref->dir[j] = '/';

                    av_log(c->fc, AV_LOG_DEBUG, "dir %s\n", dref->dir);

                } else

                    avio_skip(pb, len);

            }

        }

        avio_seek(pb, next, SEEK_SET);

    }

    return 0;

}
