| Index: patched-ffmpeg-mt/libavcodec/vc1_asftoannexg_bsf.c
|
| ===================================================================
|
| --- patched-ffmpeg-mt/libavcodec/vc1_asftoannexg_bsf.c (revision 41250)
|
| +++ patched-ffmpeg-mt/libavcodec/vc1_asftoannexg_bsf.c (working copy)
|
| @@ -180,3 +180,126 @@
|
| asftoannexg_filter,
|
| asftoannexg_close,
|
| };
|
| +/*
|
| + * copyright (c) 2010 Google Inc.
|
| + *
|
| + * 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
|
| + */
|
| +
|
| +#include "avcodec.h"
|
| +#include "bytestream.h"
|
| +#include "vc1.h"
|
| +
|
| +typedef struct ASFTOANNEXGBSFContext {
|
| + int frames;
|
| + uint8_t *seq_header;
|
| + int seq_header_size;
|
| + uint8_t *ep_header;
|
| + int ep_header_size;
|
| +} ASFTOANNEXGBSFContext;
|
| +
|
| +static int parse_extradata(AVCodecContext *avctx, ASFTOANNEXGBSFContext *ctx, uint8_t *extradata, int extradata_size) {
|
| + const uint8_t *start = extradata;
|
| + const uint8_t *end = extradata + extradata_size;
|
| + const uint8_t *next;
|
| + int size;
|
| +
|
| + if(extradata_size < 16) {
|
| + av_log(avctx, AV_LOG_ERROR, "Extradata size too small: %i\n", extradata_size);
|
| + return -1;
|
| + }
|
| +
|
| + start = find_next_marker(start, end);
|
| + next = start;
|
| + for(; next < end; start = next){
|
| + next = find_next_marker(start + 4, end);
|
| + size = next - start;
|
| + if(size <= 0) continue;
|
| + switch(AV_RB32(start)){
|
| + case VC1_CODE_SEQHDR:
|
| + ctx->seq_header = av_malloc(size);
|
| + ctx->seq_header_size = size;
|
| + memcpy(ctx->seq_header, start, size);
|
| + break;
|
| + case VC1_CODE_ENTRYPOINT:
|
| + ctx->ep_header = av_malloc(size);
|
| + ctx->ep_header_size = size;
|
| + memcpy(ctx->ep_header, start, size);
|
| + break;
|
| + default:
|
| + break;
|
| + }
|
| + }
|
| +
|
| + if(!ctx->seq_header || !ctx->ep_header) {
|
| + av_log(avctx, AV_LOG_ERROR, "Incomplete extradata\n");
|
| + return -1;
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| +static int asftoannexg_filter(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
|
| + uint8_t **poutbuf, int *poutbuf_size,
|
| + const uint8_t *buf, int buf_size, int keyframe){
|
| + ASFTOANNEXGBSFContext* ctx = (ASFTOANNEXGBSFContext*)bsfc->priv_data;
|
| +
|
| + if (avctx->codec_id != CODEC_ID_VC1) {
|
| + av_log(avctx, AV_LOG_ERROR, "Only VC1 Advanced profile is accepted!\n");
|
| + return -1;
|
| + }
|
| +
|
| + if (!ctx->frames && parse_extradata(avctx, ctx, avctx->extradata, avctx->extradata_size) < 0) {
|
| + av_log(avctx, AV_LOG_ERROR, "Cannot parse extra data!\n");
|
| + return -1;
|
| + }
|
| +
|
| + uint8_t* bs;
|
| + if (keyframe) {
|
| + // If this is the keyframe, need to put sequence header and entry point header.
|
| + *poutbuf_size = ctx->seq_header_size + ctx->ep_header_size + 4 + buf_size;
|
| + *poutbuf = av_malloc(*poutbuf_size);
|
| + bs = *poutbuf;
|
| +
|
| + memcpy(bs, ctx->seq_header, ctx->seq_header_size);
|
| + bs += ctx->seq_header_size;
|
| + memcpy(bs, ctx->ep_header, ctx->ep_header_size);
|
| + bs += ctx->ep_header_size;
|
| + } else {
|
| + *poutbuf_size = 4 + buf_size;
|
| + *poutbuf = av_malloc(*poutbuf_size);
|
| + bs = *poutbuf;
|
| + }
|
| +
|
| + // Put the frame start code and frame data.
|
| + bytestream_put_be32(&bs, VC1_CODE_FRAME);
|
| + memcpy(bs, buf, buf_size);
|
| + ++ctx->frames;
|
| + return 0;
|
| +}
|
| +
|
| +static void asftoannexg_close(AVBitStreamFilterContext *bsfc) {
|
| + ASFTOANNEXGBSFContext *ctx = bsfc->priv_data;
|
| + av_freep(&ctx->seq_header);
|
| + av_freep(&ctx->ep_header);
|
| +}
|
| +
|
| +AVBitStreamFilter vc1_asftoannexg_bsf = {
|
| + "vc1_asftoannexg",
|
| + sizeof(ASFTOANNEXGBSFContext),
|
| + asftoannexg_filter,
|
| + asftoannexg_close,
|
| +};
|
|
|