ffmpeg生成带关键帧头信息的flv文件(四)

static int flv_write_packet(AVFormatContext *s, AVPacket *pkt)

{

    AVIOContext *pb = s->pb;

    AVCodecContext *enc = s->streams[pkt->stream_index]->codec;

    FLVContext *flv = (FLVContext*)s->priv_data;

    FLVStreamContext *sc = (FLVStreamContext*)s->streams[pkt->stream_index]->priv_data;

    unsigned ts;

    int size= pkt->size;

    uint8_t *data= NULL;

    int flags, flags_size;

 

    /********** Add KeyFrame Index ***********************************/

    int64_t vbegin_offset = avio_tell(pb);

    /************************************************************************/

 

//    av_log(s, AV_LOG_DEBUG, "type:%d pts: %"PRId64" size:%d\n", enc->codec_type, timestamp, size);

 

    if(enc->codec_id == CODEC_ID_VP6 || enc->codec_id == CODEC_ID_VP6F ||

       enc->codec_id == CODEC_ID_AAC)

        flags_size= 2;

    else if(enc->codec_id == CODEC_ID_H264 || enc->codec_id == CODEC_ID_MPEG4)

        flags_size= 5;

    else

        flags_size= 1;

 

    if (enc->codec_type == AVMEDIA_TYPE_VIDEO) {

        avio_w8(pb, FLV_TAG_TYPE_VIDEO);

 

        flags = enc->codec_tag;

        if(flags == 0) {

            av_log(enc, AV_LOG_ERROR, "video codec %s not compatible with flv\n", avcodec_get_name(enc->codec_id));

            return -1;

        }

 

        flags |= pkt->flags & AV_PKT_FLAG_KEY ? FLV_FRAME_KEY : FLV_FRAME_INTER;

    } else if (enc->codec_type == AVMEDIA_TYPE_AUDIO) {

        flags = get_audio_flags(enc);

 

        assert(size);

 

        avio_w8(pb, FLV_TAG_TYPE_AUDIO);

    } else {

        // In-band flv metadata ("scriptdata")

        assert(enc->codec_type == AVMEDIA_TYPE_DATA);

        avio_w8(pb, FLV_TAG_TYPE_META);

        flags_size = 0;

        flags = 0;

    }

 

    if (enc->codec_id == CODEC_ID_H264 || enc->codec_id == CODEC_ID_MPEG4) {

        /* check if extradata looks like mp4 formated */

        if (enc->extradata_size > 0 && *(uint8_t*)enc->extradata != 1) {

            if (ff_avc_parse_nal_units_buf(pkt->data, &data, &size) < 0)

                return -1;

        }

    } else if (enc->codec_id == CODEC_ID_AAC && pkt->size > 2 &&

               (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) {

        av_log(s, AV_LOG_ERROR, "malformated aac bitstream, use -absf aac_adtstoasc\n");

        return -1;

    }

    if (flv->delay == AV_NOPTS_VALUE)

        flv->delay = -pkt->dts;

    if (pkt->dts < -flv->delay) {

        av_log(s, AV_LOG_WARNING, "Packets are not in the proper order with "

                                  "respect to DTS\n");

        return AVERROR(EINVAL);

    }

 

    ts = pkt->dts + flv->delay; // add delay to force positive dts

 

    /* check Speex packet duration */

    if (enc->codec_id == CODEC_ID_SPEEX && ts - sc->last_ts > 160) {

        av_log(s, AV_LOG_WARNING, "Warning: Speex stream has more than "

                                  "8 frames per packet. Adobe Flash "

                                  "Player cannot handle this!\n");

    }

 

    if (sc->last_ts < ts)

        sc->last_ts = ts;

 

    avio_wb24(pb,size + flags_size);

    avio_wb24(pb,ts);

    avio_w8(pb,(ts >> 24) & 0x7F); // timestamps are 32bits _signed_

    avio_wb24(pb,flv->reserved);

 

    if(flags_size)

        avio_w8(pb,flags);

 

    if (enc->codec_id == CODEC_ID_VP6)

        avio_w8(pb,0);

    if (enc->codec_id == CODEC_ID_VP6F)

        avio_w8(pb, enc->extradata_size ? enc->extradata[0] : 0);

    else if (enc->codec_id == CODEC_ID_AAC)

        avio_w8(pb,1); // AAC raw

    else if (enc->codec_id == CODEC_ID_H264 || enc->codec_id == CODEC_ID_MPEG4) {

        avio_w8(pb,1); // AVC NALU

        avio_wb24(pb,pkt->pts - pkt->dts);

    }

 

    avio_write(pb, data ? data : pkt->data, size);

 

    avio_wb32(pb,size+flags_size+11); // previous tag size

    flv->duration = FFMAX(flv->duration, pkt->pts + flv->delay + pkt->duration);

 

    /********** Add KeyFrame Index ***********************************/

    if (enc->codec_type == AVMEDIA_TYPE_VIDEO)

    {

        flv->videosize += (avio_tell(pb) - vbegin_offset);

        flv->lasttimestamp = flv->acurframeindex / flv->framerate;

        if (pkt->flags & AV_PKT_FLAG_KEY)

        {

            flv->lastkeyframelocation  = vbegin_offset;

            flv->lastkeyframetimestamp = flv->acurframeindex / flv->framerate;

 

            flv->filepositions.Add(flv->lastkeyframelocation);

            flv->filetimes.Add(flv->lastkeyframetimestamp);

        }

 

        flv->acurframeindex++;

    }

    else if (enc->codec_type == AVMEDIA_TYPE_AUDIO)

    {

        flv->audiosize += (avio_tell(pb) - vbegin_offset);

    }

    /************************************************************************/

 

    avio_flush(pb);

 

    av_free(data);

 

    return pb->error;

}

 

static AVCodecTag* ff_flv_tag[] = {(AVCodecTag*)flv_video_codec_ids, (AVCodecTag*)flv_audio_codec_ids, 0};

AVOutputFormat my_ff_flv_muxer = {

    "flv",

    "FLV format",

    "video/x-flv",

    "flv",

    sizeof(FLVContext),

    CODEC_ID_ADPCM_SWF,

    CODEC_ID_FLV1,

    flv_write_header,

    flv_write_packet,

    flv_write_trailer,

    AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS,

    NULL,

    NULL,

    ff_flv_tag,

};

 

};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值