Chinaunix首页 | 论坛 | 博客
  • 博客访问: 951630
  • 博文数量: 108
  • 博客积分: 3243
  • 博客等级: 中校
  • 技术积分: 964
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-15 22:09
文章分类

全部博文(108)

文章存档

2020年(2)

2019年(1)

2018年(2)

2017年(9)

2016年(20)

2015年(1)

2013年(1)

2012年(12)

2011年(28)

2010年(27)

2009年(4)

2008年(1)

分类: C/C++

2012-05-02 17:21:14

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,

};

 

};

阅读(9489) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~