Chinaunix首页 | 论坛 | 博客
  • 博客访问: 972402
  • 博文数量: 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:08:09

     普通flv文件头信息中不带关键帧信息,在网页播放器中播放时,seek速度很慢,为了加快flvseek速度,我们可以在flv的头信息中写入关键帧信息.

      主要方法为;在写头信息时预留一定的位置用来写关键帧信息,在写包时包关键帧信息先保存起来,等到写文件结束时,根据需要把保存的关键帧信息写到预留的头信息中.

 

/*

 * FLV muxer

 * Copyright (c) 2003 The FFmpeg Project

 *

 * 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 "stdafx.h"

#include "vxtempl.h"

extern "C"

{

#include "libavutil/intreadwrite.h"

#include "libavutil/intfloat.h"

#include "avformat.h"

#include "flv.h"

#include "internal.h"

#include "avc.h"

#include "metadata.h"

#include "libavutil/dict.h"

 

#undef NDEBUG

#include

 

static const AVCodecTag flv_video_codec_ids[] = {

    {CODEC_ID_FLV1,    FLV_CODECID_H263  },

    {CODEC_ID_H263,    FLV_CODECID_REALH263},

    {CODEC_ID_MPEG4,   FLV_CODECID_MPEG4 },

    {CODEC_ID_FLASHSV, FLV_CODECID_SCREEN},

    {CODEC_ID_FLASHSV2, FLV_CODECID_SCREEN2},

    {CODEC_ID_VP6F,    FLV_CODECID_VP6   },

    {CODEC_ID_VP6,     FLV_CODECID_VP6   },

    {CODEC_ID_H264,    FLV_CODECID_H264  },

    {CODEC_ID_NONE,    0}

};

 

static const AVCodecTag flv_audio_codec_ids[] = {

    {CODEC_ID_MP3,       FLV_CODECID_MP3    >> FLV_AUDIO_CODECID_OFFSET},

    {CODEC_ID_PCM_U8,    FLV_CODECID_PCM    >> FLV_AUDIO_CODECID_OFFSET},

    {CODEC_ID_PCM_S16BE, FLV_CODECID_PCM    >> FLV_AUDIO_CODECID_OFFSET},

    {CODEC_ID_PCM_S16LE, FLV_CODECID_PCM_LE >> FLV_AUDIO_CODECID_OFFSET},

    {CODEC_ID_ADPCM_SWF, FLV_CODECID_ADPCM  >> FLV_AUDIO_CODECID_OFFSET},

    {CODEC_ID_AAC,       FLV_CODECID_AAC    >> FLV_AUDIO_CODECID_OFFSET},

    {CODEC_ID_NELLYMOSER, FLV_CODECID_NELLYMOSER >> FLV_AUDIO_CODECID_OFFSET},

    {CODEC_ID_SPEEX,     FLV_CODECID_SPEEX  >> FLV_AUDIO_CODECID_OFFSET},

    {CODEC_ID_NONE,      0}

};

 

#define MAX_FLV_KEY_FRAME       1500

 

typedef struct FLVContext {

    int reserved;

    double framerate;

 

    int64_t duration_offset;

    int64_t duration;

    int64_t datasize_offset;

    int64_t datasize;

    int64_t videosize_offset;

    int64_t videosize;

    int64_t audiosize_offset;

    int64_t audiosize;

    int64_t filesize_offset;

 

    int64_t delay;      ///< first dts delay (needed for AVC & Speex)

 

    int acurframeindex;

 

    int64_t lasttimestamp_offset;

    double lasttimestamp;

    int64_t lastkeyframetimestamp_offset;

    double lastkeyframetimestamp;

    int64_t lastkeyframelocation_offset;

    int64_t lastkeyframelocation;

 

    int64_t filepositions_offset;

    CVxArray filepositions;

    int64_t filetimes_offset;

    CVxArray<double> filetimes;

 

    int64_t filetimesend_Pos;

    int64_t datastart_offset;

} FLVContext;

 

typedef struct FLVStreamContext {

    int64_t last_ts;    ///< last timestamp for each stream

} FLVStreamContext;

 

static int get_audio_flags(AVCodecContext *enc){

    int flags = (enc->bits_per_coded_sample == 16) ? FLV_SAMPLESSIZE_16BIT : FLV_SAMPLESSIZE_8BIT;

 

    if (enc->codec_id == CODEC_ID_AAC) // specs force these parameters

        return FLV_CODECID_AAC | FLV_SAMPLERATE_44100HZ | FLV_SAMPLESSIZE_16BIT | FLV_STEREO;

    else if (enc->codec_id == CODEC_ID_SPEEX) {

        if (enc->sample_rate != 16000) {

            av_log(enc, AV_LOG_ERROR, "flv only supports wideband (16kHz) Speex audio\n");

            return -1;

        }

        if (enc->channels != 1) {

            av_log(enc, AV_LOG_ERROR, "flv only supports mono Speex audio\n");

            return -1;

        }

        return FLV_CODECID_SPEEX | FLV_SAMPLERATE_11025HZ | FLV_SAMPLESSIZE_16BIT;

    } else {

    switch (enc->sample_rate) {

        case    44100:

            flags |= FLV_SAMPLERATE_44100HZ;

            break;

        case    22050:

            flags |= FLV_SAMPLERATE_22050HZ;

            break;

        case    11025:

            flags |= FLV_SAMPLERATE_11025HZ;

            break;

        case    16000: //nellymoser only

        case     8000: //nellymoser only

        case     5512: //not mp3

            if(enc->codec_id != CODEC_ID_MP3){

                flags |= FLV_SAMPLERATE_SPECIAL;

                break;

            }

        default:

            av_log(enc, AV_LOG_ERROR, "flv does not support that sample rate, choose from (44100, 22050, 11025).\n");

            return -1;

    }

    }

 

    if (enc->channels > 1) {

        flags |= FLV_STEREO;

    }

 

    switch(enc->codec_id){

    case CODEC_ID_MP3:

        flags |= FLV_CODECID_MP3    | FLV_SAMPLESSIZE_16BIT;

        break;

    case CODEC_ID_PCM_U8:

        flags |= FLV_CODECID_PCM    | FLV_SAMPLESSIZE_8BIT;

        break;

    case CODEC_ID_PCM_S16BE:

        flags |= FLV_CODECID_PCM    | FLV_SAMPLESSIZE_16BIT;

        break;

    case CODEC_ID_PCM_S16LE:

        flags |= FLV_CODECID_PCM_LE | FLV_SAMPLESSIZE_16BIT;

        break;

    case CODEC_ID_ADPCM_SWF:

        flags |= FLV_CODECID_ADPCM | FLV_SAMPLESSIZE_16BIT;

        break;

    case CODEC_ID_NELLYMOSER:

        if (enc->sample_rate == 8000) {

            flags |= FLV_CODECID_NELLYMOSER_8KHZ_MONO | FLV_SAMPLESSIZE_16BIT;

        } else if (enc->sample_rate == 16000) {

            flags |= FLV_CODECID_NELLYMOSER_16KHZ_MONO | FLV_SAMPLESSIZE_16BIT;

        } else {

            flags |= FLV_CODECID_NELLYMOSER | FLV_SAMPLESSIZE_16BIT;

        }

        break;

    case 0:

        flags |= enc->codec_tag<<4;

        break;

    default:

        av_log(enc, AV_LOG_ERROR, "codec not compatible with flv\n");

        return -1;

    }

 

    return flags;

}

 

static void put_amf_string(AVIOContext *pb, const char *str)

{

    size_t len = strlen(str);

    avio_wb16(pb, len);

    avio_write(pb, (const unsigned char *)str, len);

}

 

static void put_avc_eos_tag(AVIOContext *pb, unsigned ts) {

    avio_w8(pb, FLV_TAG_TYPE_VIDEO);

    avio_wb24(pb, 5);  /* Tag Data Size */

    avio_wb24(pb, ts);  /* lower 24 bits of timestamp in ms*/

    avio_w8(pb, (ts >> 24) & 0x7F);  /* MSB of ts in ms*/

    avio_wb24(pb, 0);  /* StreamId = 0 */

    avio_w8(pb, 23);  /* ub[4] FrameType = 1, ub[4] CodecId = 7 */

    avio_w8(pb, 2);  /* AVC end of sequence */

    avio_wb24(pb, 0);  /* Always 0 for AVC EOS. */

    avio_wb32(pb, 16);  /* Size of FLV tag */

}

 

static void put_amf_dword_array(AVIOContext *pb, DWORD dw)

{

    avio_w8(pb, AMF_DATA_TYPE_ARRAY);

    avio_wb32(pb, dw);

}

 

static void put_amf_double(AVIOContext *pb, double d)

{

    avio_w8(pb, AMF_DATA_TYPE_NUMBER);

    avio_wb64(pb, av_double2int(d));

}

 

static void put_amf_byte(AVIOContext *pb, BYTE abyte)

{

    avio_w8(pb, abyte);

}

 

static void put_amf_bool(AVIOContext *pb, int b) {

    avio_w8(pb, AMF_DATA_TYPE_BOOL);

    avio_w8(pb, !!b);

}

 

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