?? asf.c
字號:
/* * ASF compatible encoder and decoder. * Copyright (c) 2000, 2001 Fabrice Bellard. * * This library 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 of the License, or (at your option) any later version. * * This library 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 this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include "avformat.h"#include "avi.h"#include "mpegaudio.h"#define PACKET_SIZE 3200#define PACKET_HEADER_SIZE 12#define FRAME_HEADER_SIZE 17typedef struct { int num; int seq; /* use for reading */ AVPacket pkt; int frag_offset; int timestamp; int64_t duration; int ds_span; /* descrambling */ int ds_packet_size; int ds_chunk_size; int ds_data_size; int ds_silence_data;} ASFStream;typedef struct { uint32_t v1; uint16_t v2; uint16_t v3; uint8_t v4[8];} GUID;typedef struct { GUID guid; // generated by client computer uint64_t file_size; // in bytes // invalid if broadcasting uint64_t create_time; // time of creation, in 100-nanosecond units since 1.1.1601 // invalid if broadcasting uint64_t packets_count; // how many packets are there in the file // invalid if broadcasting uint64_t play_time; // play time, in 100-nanosecond units // invalid if broadcasting uint64_t send_time; // time to send file, in 100-nanosecond units // invalid if broadcasting (could be ignored) uint32_t preroll; // timestamp of the first packet, in milliseconds // if nonzero - substract from time uint32_t ignore; // preroll is 64bit - but let's just ignore it uint32_t flags; // 0x01 - broadcast // 0x02 - seekable // rest is reserved should be 0 uint32_t min_pktsize; // size of a data packet // invalid if broadcasting uint32_t max_pktsize; // shall be the same as for min_pktsize // invalid if broadcasting uint32_t max_bitrate; // bandwith of stream in bps // should be the sum of bitrates of the // individual media streams} ASFMainHeader;typedef struct { int seqno; int packet_size; int is_streamed; int asfid2avid[128]; /* conversion table from asf ID 2 AVStream ID */ ASFStream streams[128]; /* it's max number and it's not that big */ /* non streamed additonnal info */ int64_t nb_packets; int64_t duration; /* in 100ns units */ /* packet filling */ int packet_size_left; int packet_timestamp_start; int packet_timestamp_end; int packet_nb_frames; uint8_t packet_buf[PACKET_SIZE]; ByteIOContext pb; /* only for reading */ uint64_t data_offset; /* begining of the first data packet */ ASFMainHeader hdr; int packet_flags; int packet_property; int packet_timestamp; int packet_segsizetype; int packet_segments; int packet_seq; int packet_replic_size; int packet_key_frame; int packet_padsize; int packet_frag_offset; int packet_frag_size; int packet_frag_timestamp; int packet_multi_size; int packet_obj_size; int packet_time_delta; int packet_time_start; int stream_index; ASFStream* asf_st; /* currently decoded stream */} ASFContext;static const GUID asf_header = { 0x75B22630, 0x668E, 0x11CF, { 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C },};static const GUID file_header = { 0x8CABDCA1, 0xA947, 0x11CF, { 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 },};static const GUID stream_header = { 0xB7DC0791, 0xA9B7, 0x11CF, { 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 },};static const GUID audio_stream = { 0xF8699E40, 0x5B4D, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B },};static const GUID audio_conceal_none = { // 0x49f1a440, 0x4ece, 0x11d0, { 0xa3, 0xac, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6 }, // New value lifted from avifile 0x20fb5700, 0x5b55, 0x11cf, { 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b },};static const GUID video_stream = { 0xBC19EFC0, 0x5B4D, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B },};static const GUID video_conceal_none = { 0x20FB5700, 0x5B55, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B },};static const GUID comment_header = { 0x75b22633, 0x668e, 0x11cf, { 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c },};static const GUID codec_comment_header = { 0x86D15240, 0x311D, 0x11D0, { 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 },};static const GUID codec_comment1_header = { 0x86d15241, 0x311d, 0x11d0, { 0xa3, 0xa4, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6 },};static const GUID data_header = { 0x75b22636, 0x668e, 0x11cf, { 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c },};static const GUID index_guid = { 0x33000890, 0xe5b1, 0x11cf, { 0x89, 0xf4, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xcb },};static const GUID head1_guid = { 0x5fbf03b5, 0xa92e, 0x11cf, { 0x8e, 0xe3, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65 },};static const GUID head2_guid = { 0xabd3d211, 0xa9ba, 0x11cf, { 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65 },};/* I am not a number !!! This GUID is the one found on the PC used to generate the stream */static const GUID my_guid = { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 },};#ifdef CONFIG_ENCODERSstatic void put_guid(ByteIOContext *s, const GUID *g){ int i; put_le32(s, g->v1); put_le16(s, g->v2); put_le16(s, g->v3); for(i=0;i<8;i++) put_byte(s, g->v4[i]);}static void put_str16(ByteIOContext *s, const char *tag){ int c; put_le16(s,strlen(tag) + 1); for(;;) { c = (uint8_t)*tag++; put_le16(s, c); if (c == '\0') break; }}static void put_str16_nolen(ByteIOContext *s, const char *tag){ int c; for(;;) { c = (uint8_t)*tag++; put_le16(s, c); if (c == '\0') break; }}static int64_t put_header(ByteIOContext *pb, const GUID *g){ int64_t pos; pos = url_ftell(pb); put_guid(pb, g); put_le64(pb, 24); return pos;}/* update header size */static void end_header(ByteIOContext *pb, int64_t pos){ int64_t pos1; pos1 = url_ftell(pb); url_fseek(pb, pos + 16, SEEK_SET); put_le64(pb, pos1 - pos); url_fseek(pb, pos1, SEEK_SET);}/* write an asf chunk (only used in streaming case) */static void put_chunk(AVFormatContext *s, int type, int payload_length, int flags){ ASFContext *asf = s->priv_data; ByteIOContext *pb = &s->pb; int length; length = payload_length + 8; put_le16(pb, type); put_le16(pb, length); put_le32(pb, asf->seqno); put_le16(pb, flags); /* unknown bytes */ put_le16(pb, length); asf->seqno++;}/* convert from unix to windows time */static int64_t unix_to_file_time(int ti){ int64_t t; t = ti * int64_t_C(10000000); t += int64_t_C(116444736000000000); return t;}/* write the header (used two times if non streamed) */static int asf_write_header1(AVFormatContext *s, int64_t file_size, int64_t data_chunk_size){ ASFContext *asf = s->priv_data; ByteIOContext *pb = &s->pb; int header_size, n, extra_size, extra_size2, wav_extra_size, file_time; int has_title; AVCodecContext *enc; int64_t header_offset, cur_pos, hpos; int bit_rate; has_title = (s->title[0] || s->author[0] || s->copyright[0] || s->comment[0]); bit_rate = 0; for(n=0;n<s->nb_streams;n++) { enc = &s->streams[n]->codec; bit_rate += enc->bit_rate; } if (asf->is_streamed) { put_chunk(s, 0x4824, 0, 0xc00); /* start of stream (length will be patched later) */ } put_guid(pb, &asf_header); put_le64(pb, -1); /* header length, will be patched after */ put_le32(pb, 3 + has_title + s->nb_streams); /* number of chunks in header */ put_byte(pb, 1); /* ??? */ put_byte(pb, 2); /* ??? */ /* file header */ header_offset = url_ftell(pb); hpos = put_header(pb, &file_header); put_guid(pb, &my_guid); put_le64(pb, file_size); file_time = 0; put_le64(pb, unix_to_file_time(file_time)); put_le64(pb, asf->nb_packets); /* number of packets */ put_le64(pb, asf->duration); /* end time stamp (in 100ns units) */ put_le64(pb, asf->duration); /* duration (in 100ns units) */ put_le32(pb, 0); /* start time stamp */ put_le32(pb, 0); /* ??? */ put_le32(pb, asf->is_streamed ? 1 : 0); /* ??? */ put_le32(pb, asf->packet_size); /* packet size */ put_le32(pb, asf->packet_size); /* packet size */ put_le32(pb, bit_rate); /* Nominal data rate in bps */ end_header(pb, hpos); /* unknown headers */ hpos = put_header(pb, &head1_guid); put_guid(pb, &head2_guid); put_le32(pb, 6); put_le16(pb, 0); end_header(pb, hpos); /* title and other infos */ if (has_title) { hpos = put_header(pb, &comment_header); put_le16(pb, 2 * (strlen(s->title) + 1)); put_le16(pb, 2 * (strlen(s->author) + 1)); put_le16(pb, 2 * (strlen(s->copyright) + 1)); put_le16(pb, 2 * (strlen(s->comment) + 1)); put_le16(pb, 0); put_str16_nolen(pb, s->title); put_str16_nolen(pb, s->author); put_str16_nolen(pb, s->copyright); put_str16_nolen(pb, s->comment); end_header(pb, hpos); } /* stream headers */ for(n=0;n<s->nb_streams;n++) { int64_t es_pos; // ASFStream *stream = &asf->streams[n]; enc = &s->streams[n]->codec; asf->streams[n].num = n + 1; asf->streams[n].seq = 0; switch(enc->codec_type) { case CODEC_TYPE_AUDIO: wav_extra_size = 0; extra_size = 18 + wav_extra_size; extra_size2 = 0; break; default: case CODEC_TYPE_VIDEO: wav_extra_size = 0; extra_size = 0x33; extra_size2 = 0; break; } hpos = put_header(pb, &stream_header); if (enc->codec_type == CODEC_TYPE_AUDIO) { put_guid(pb, &audio_stream); put_guid(pb, &audio_conceal_none); } else { put_guid(pb, &video_stream); put_guid(pb, &video_conceal_none); } put_le64(pb, 0); /* ??? */ es_pos = url_ftell(pb); put_le32(pb, extra_size); /* wav header len */ put_le32(pb, extra_size2); /* additional data len */ put_le16(pb, n + 1); /* stream number */ put_le32(pb, 0); /* ??? */ if (enc->codec_type == CODEC_TYPE_AUDIO) { /* WAVEFORMATEX header */ int wavsize = put_wav_header(pb, enc); if (wavsize < 0) return -1; if (wavsize != extra_size) { cur_pos = url_ftell(pb); url_fseek(pb, es_pos, SEEK_SET); put_le32(pb, wavsize); /* wav header len */ url_fseek(pb, cur_pos, SEEK_SET); } } else { put_le32(pb, enc->width); put_le32(pb, enc->height); put_byte(pb, 2); /* ??? */ put_le16(pb, 40); /* size */ /* BITMAPINFOHEADER header */ put_bmp_header(pb, enc, codec_bmp_tags, 1); } end_header(pb, hpos); } /* media comments */ hpos = put_header(pb, &codec_comment_header); put_guid(pb, &codec_comment1_header); put_le32(pb, s->nb_streams); for(n=0;n<s->nb_streams;n++) { AVCodec *p; enc = &s->streams[n]->codec; p = avcodec_find_encoder(enc->codec_id); put_le16(pb, asf->streams[n].num); put_str16(pb, p ? p->name : enc->codec_name); put_le16(pb, 0); /* no parameters */ /* id */ if (enc->codec_type == CODEC_TYPE_AUDIO) { put_le16(pb, 2); if(!enc->codec_tag) enc->codec_tag = codec_get_tag(codec_wav_tags, enc->codec_id); if(!enc->codec_tag) return -1; put_le16(pb, enc->codec_tag); } else { put_le16(pb, 4); if(!enc->codec_tag) enc->codec_tag = codec_get_tag(codec_bmp_tags, enc->codec_id); if(!enc->codec_tag) return -1; put_le32(pb, enc->codec_tag); } } end_header(pb, hpos); /* patch the header size fields */ cur_pos = url_ftell(pb);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -