Ejemplo n.º 1
0
static int dhav_read_header(AVFormatContext *s)
{
    DHAVContext *dhav = s->priv_data;
    uint8_t signature[5];

    ffio_ensure_seekback(s->pb, 5);
    avio_read(s->pb, signature, sizeof(signature));
    if (!memcmp(signature, "DAHUA", 5))
        avio_skip(s->pb, 0x400 - 5);
    else
        avio_seek(s->pb, -5, SEEK_CUR);

    s->ctx_flags |= AVFMTCTX_NOHEADER;
    dhav->video_stream_index = -1;
    dhav->audio_stream_index = -1;

    return 0;
}
Ejemplo n.º 2
0
static int mpjpeg_read_packet(AVFormatContext *s, AVPacket *pkt)
{
    int size;
    int ret;

    MPJPEGDemuxContext *mpjpeg = s->priv_data;
    if (mpjpeg->boundary == NULL) {
        uint8_t* boundary = NULL;
        if (mpjpeg->strict_mime_boundary) {
            boundary = mpjpeg_get_boundary(s->pb);
        }
        if (boundary != NULL) {
            mpjpeg->boundary = boundary;
            mpjpeg->searchstr = av_asprintf( "\r\n%s\r\n", boundary );
        } else {
            mpjpeg->boundary = av_strdup("--");
            mpjpeg->searchstr = av_strdup("\r\n--");
        }
        if (!mpjpeg->boundary || !mpjpeg->searchstr) {
            av_freep(&mpjpeg->boundary);
            av_freep(&mpjpeg->searchstr);
            return AVERROR(ENOMEM);
        }
        mpjpeg->searchstr_len = strlen(mpjpeg->searchstr);
    }

    ret = parse_multipart_header(s->pb, &size, mpjpeg->boundary, s);


    if (ret < 0)
        return ret;

    if (size > 0) {
        /* size has been provided to us in MIME header */
        ret = av_get_packet(s->pb, pkt, size);
    } else {
        /* no size was given -- we read until the next boundary or end-of-file */
        int remaining = 0, len;

        const int read_chunk = 2048;
        av_init_packet(pkt);
        pkt->data = NULL;
        pkt->size = 0;
        pkt->pos  = avio_tell(s->pb);

        /* we may need to return as much as all we've read back to the buffer */
        ffio_ensure_seekback(s->pb, read_chunk);

        while ((ret = av_append_packet(s->pb, pkt, read_chunk - remaining)) >= 0) {
            /* scan the new data */
            char *start;

            len = ret + remaining;
            start = pkt->data + pkt->size - len;
            do {
                if (!memcmp(start, mpjpeg->searchstr, mpjpeg->searchstr_len)) {
                    // got the boundary! rewind the stream
                    avio_seek(s->pb, -(len-2), SEEK_CUR);
                    pkt->size -= (len-2);
                    return pkt->size;
                }
                len--;
                start++;
            } while (len >= mpjpeg->searchstr_len);
            remaining = len;
        }

        /* error or EOF occurred */
        if (ret == AVERROR_EOF) {
            ret = pkt->size > 0 ? pkt->size : AVERROR_EOF;
        } else {
            av_packet_unref(pkt);
        }
    }

    return ret;
}
Ejemplo n.º 3
0
static int apng_read_packet(AVFormatContext *s, AVPacket *pkt)
{
    APNGDemuxContext *ctx = s->priv_data;
    int ret;
    int64_t size;
    AVIOContext *pb = s->pb;
    uint32_t len, tag;

    /*
     * fcTL chunk length, in bytes:
     *  4 (length)
     *  4 (tag)
     * 26 (actual chunk)
     *  4 (crc) bytes
     * and needed next:
     *  4 (length)
     *  4 (tag (must be fdAT or IDAT))
     */
    /* if num_play is not 1, then the seekback is already guaranteed */
    if (ctx->num_play == 1 && (ret = ffio_ensure_seekback(pb, 46)) < 0)
        return ret;

    len = avio_rb32(pb);
    tag = avio_rl32(pb);
    switch (tag) {
    case MKTAG('f', 'c', 'T', 'L'):
        if (len != 26)
            return AVERROR_INVALIDDATA;

        if ((ret = decode_fctl_chunk(s, ctx, pkt)) < 0)
            return ret;

        /* fcTL must precede fdAT or IDAT */
        len = avio_rb32(pb);
        tag = avio_rl32(pb);
        if (len > 0x7fffffff ||
            tag != MKTAG('f', 'd', 'A', 'T') &&
            tag != MKTAG('I', 'D', 'A', 'T'))
            return AVERROR_INVALIDDATA;

        size = 38 /* fcTL */ + 8 /* len, tag */ + len + 4 /* crc */;
        if (size > INT_MAX)
            return AVERROR(EINVAL);

        if ((ret = avio_seek(pb, -46, SEEK_CUR)) < 0 ||
            (ret = av_append_packet(pb, pkt, size)) < 0)
            return ret;

        if (ctx->num_play == 1 && (ret = ffio_ensure_seekback(pb, 8)) < 0)
            return ret;

        len = avio_rb32(pb);
        tag = avio_rl32(pb);
        while (tag &&
               tag != MKTAG('f', 'c', 'T', 'L') &&
               tag != MKTAG('I', 'E', 'N', 'D')) {
            if (len > 0x7fffffff)
                return AVERROR_INVALIDDATA;
            if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0 ||
                (ret = av_append_packet(pb, pkt, len + 12)) < 0)
                return ret;
            if (ctx->num_play == 1 && (ret = ffio_ensure_seekback(pb, 8)) < 0)
                return ret;
            len = avio_rb32(pb);
            tag = avio_rl32(pb);
        }
        if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0)
            return ret;

        if (ctx->is_key_frame)
            pkt->flags |= AV_PKT_FLAG_KEY;
        return ret;
    case MKTAG('I', 'E', 'N', 'D'):
        ctx->cur_loop++;
        if (ctx->ignore_loop || ctx->num_play >= 1 && ctx->cur_loop == ctx->num_play) {
            avio_seek(pb, -8, SEEK_CUR);
            return AVERROR_EOF;
        }
        if ((ret = avio_seek(pb, s->streams[0]->codec->extradata_size + 8, SEEK_SET)) < 0)
            return ret;
        return 0;
    default:
        {
        char tag_buf[5];

        av_get_codec_tag_string(tag_buf, sizeof(tag_buf), tag);
        avpriv_request_sample(s, "In-stream tag=%s (0x%08X) len=%"PRIu32, tag_buf, tag, len);
        avio_skip(pb, len + 4);
        }
    }

    /* Handle the unsupported yet cases */
    return AVERROR_PATCHWELCOME;
}
Ejemplo n.º 4
0
static int apng_read_header(AVFormatContext *s)
{
    APNGDemuxContext *ctx = s->priv_data;
    AVIOContext *pb = s->pb;
    uint32_t len, tag;
    AVStream *st;
    int ret = AVERROR_INVALIDDATA, acTL_found = 0;

    /* verify PNGSIG */
    if (avio_rb64(pb) != PNGSIG)
        return ret;

    /* parse IHDR (must be first chunk) */
    len = avio_rb32(pb);
    tag = avio_rl32(pb);
    if (len != 13 || tag != MKTAG('I', 'H', 'D', 'R'))
        return ret;

    st = avformat_new_stream(s, NULL);
    if (!st)
        return AVERROR(ENOMEM);

    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
    st->codec->codec_id   = AV_CODEC_ID_APNG;
    st->codec->width      = avio_rb32(pb);
    st->codec->height     = avio_rb32(pb);
    if ((ret = av_image_check_size(st->codec->width, st->codec->height, 0, s)) < 0)
        return ret;

    /* extradata will contain every chunk up to the first fcTL (excluded) */
    st->codec->extradata = av_malloc(len + 12 + FF_INPUT_BUFFER_PADDING_SIZE);
    if (!st->codec->extradata)
        return AVERROR(ENOMEM);
    st->codec->extradata_size = len + 12;
    AV_WB32(st->codec->extradata,    len);
    AV_WL32(st->codec->extradata+4,  tag);
    AV_WB32(st->codec->extradata+8,  st->codec->width);
    AV_WB32(st->codec->extradata+12, st->codec->height);
    if ((ret = avio_read(pb, st->codec->extradata+16, 9)) < 0)
        goto fail;

    while (!avio_feof(pb)) {
        if (acTL_found && ctx->num_play != 1) {
            int64_t size   = avio_size(pb);
            int64_t offset = avio_tell(pb);
            if (size < 0) {
                ret = size;
                goto fail;
            } else if (offset < 0) {
                ret = offset;
                goto fail;
            } else if ((ret = ffio_ensure_seekback(pb, size - offset)) < 0) {
                av_log(s, AV_LOG_WARNING, "Could not ensure seekback, will not loop\n");
                ctx->num_play = 1;
            }
        }
        if ((ctx->num_play == 1 || !acTL_found) &&
            ((ret = ffio_ensure_seekback(pb, 4 /* len */ + 4 /* tag */)) < 0))
            goto fail;

        len = avio_rb32(pb);
        if (len > 0x7fffffff) {
            ret = AVERROR_INVALIDDATA;
            goto fail;
        }

        tag = avio_rl32(pb);
        switch (tag) {
        case MKTAG('a', 'c', 'T', 'L'):
            if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0 ||
                (ret = append_extradata(st->codec, pb, len + 12)) < 0)
                goto fail;
            acTL_found = 1;
            ctx->num_frames = AV_RB32(st->codec->extradata + ret + 8);
            ctx->num_play   = AV_RB32(st->codec->extradata + ret + 12);
            av_log(s, AV_LOG_DEBUG, "num_frames: %"PRIu32", num_play: %"PRIu32"\n",
                                    ctx->num_frames, ctx->num_play);
            break;
        case MKTAG('f', 'c', 'T', 'L'):
            if (!acTL_found) {
               ret = AVERROR_INVALIDDATA;
               goto fail;
            }
            if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0)
                goto fail;
            return 0;
        default:
            if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0 ||
                (ret = append_extradata(st->codec, pb, len + 12)) < 0)
                goto fail;
        }
    }

fail:
    if (st->codec->extradata_size) {
        av_freep(&st->codec->extradata);
        st->codec->extradata_size = 0;
    }
    return ret;
}