分类: C/C++
2012-05-02 17:20:06
static int flv_write_trailer(AVFormatContext *s)
{
int64_t file_size;
AVIOContext *pb = s->pb;
FLVContext *flv = (FLVContext*)s->priv_data;
int i;
/* Add EOS tag */
for (i = 0; i < s->nb_streams; i++) {
AVCodecContext *enc = s->streams[i]->codec;
FLVStreamContext *sc = (FLVStreamContext*)s->streams[i]->priv_data;
if (enc->codec_type == AVMEDIA_TYPE_VIDEO &&
(enc->codec_id == CODEC_ID_H264 || enc->codec_id == CODEC_ID_MPEG4)) {
put_avc_eos_tag(pb, sc->last_ts);
}
}
file_size = avio_tell(pb);
flv->datasize = file_size - flv->datastart_offset;
/* update information */
avio_seek(pb, flv->duration_offset, SEEK_SET);
put_amf_double(pb, flv->duration / (double)1000);
/********** Add KeyFrame Index ***********************************/
avio_seek(pb, flv->datasize_offset, SEEK_SET);
put_amf_double(pb, flv->datasize);
avio_seek(pb, flv->videosize_offset, SEEK_SET);
put_amf_double(pb, flv->videosize);
avio_seek(pb, flv->audiosize_offset, SEEK_SET);
put_amf_double(pb, flv->audiosize);
/************************************************************************/
avio_seek(pb, flv->filesize_offset, SEEK_SET);
put_amf_double(pb, file_size);
/********** Add KeyFrame Index ***********************************/
avio_seek(pb, flv->lasttimestamp_offset, SEEK_SET);
put_amf_double(pb, flv->lasttimestamp);
avio_seek(pb, flv->lastkeyframetimestamp_offset, SEEK_SET);
put_amf_double(pb, flv->lastkeyframetimestamp);
avio_seek(pb, flv->lastkeyframelocation_offset, SEEK_SET);
put_amf_double(pb, flv->lastkeyframelocation);
int vKeyFrames = flv->filepositions.GetSize();
if (vKeyFrames < MAX_FLV_KEY_FRAME)
{
DWORD vfilepositions = flv->filepositions.GetSize();
avio_seek(pb, flv->filepositions_offset, SEEK_SET);
put_amf_dword_array(pb, vfilepositions);
for(int i = 0; i < vKeyFrames; i++)
{
double afilepositions = flv->filepositions.GetAt(i);
put_amf_double(pb, afilepositions);
}
// times 向¨°前¡ã移°?动¡¥
put_amf_string(pb, "times");
flv->filetimes_offset = avio_tell(pb);
DWORD vfiletimes = flv->filetimes.GetSize();
avio_seek(pb, flv->filetimes_offset, SEEK_SET);
put_amf_dword_array(pb, vfiletimes);
for(int i = 0; i < vKeyFrames; i++)
{
double afiletimes = flv->filetimes.GetAt(i);
put_amf_double(pb, afiletimes);
}
// 后¨®面?的Ì?数ºy据Y清?0
int64_t vcurfile_Pos = avio_tell(pb);
int vbytecount = flv->filetimesend_Pos - vcurfile_Pos;
for (int i = 0; i < vbytecount; i++)
{
put_amf_byte(pb, 0);
}
}
else
{
double dbStep = 1.0 * vKeyFrames / MAX_FLV_KEY_FRAME;
DWORD vfilepositions = MAX_FLV_KEY_FRAME;
avio_seek(pb, flv->filepositions_offset, SEEK_SET);
put_amf_dword_array(pb, vfilepositions);
for(int i = 0; i < MAX_FLV_KEY_FRAME; i++)
{
int vIndex = int(dbStep * i);
double afilepositions = flv->filepositions.GetAt(vIndex);
put_amf_double(pb, afilepositions);
}
DWORD vfiletimes = MAX_FLV_KEY_FRAME;
avio_seek(pb, flv->filetimes_offset, SEEK_SET);
put_amf_dword_array(pb, vfiletimes);
for(int i = 0; i < MAX_FLV_KEY_FRAME; i++)
{
int vIndex = int(dbStep * i);
double afiletimes = flv->filetimes.GetAt(vIndex);
put_amf_double(pb, afiletimes);
}
}
flv->filepositions.RemoveAll();
flv->filetimes.RemoveAll();
/************************************************************************/
avio_seek(pb, file_size, SEEK_SET);
return 0;
}