📄 asf-enc.c
字号:
enc = s->streams[n]->codec;
p = avcodec_find_encoder(enc->codec_id);
if(enc->codec_type == CODEC_TYPE_AUDIO)
put_le16(pb, 2);
else if(enc->codec_type == CODEC_TYPE_VIDEO)
put_le16(pb, 1);
else
put_le16(pb, -1);
if(enc->codec_id == CODEC_ID_WMAV2)
put_str16(pb, "Windows Media Audio V8");
else
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);
put_le16(pb, enc->codec_tag);
} else {
put_le16(pb, 4);
put_le32(pb, enc->codec_tag);
}
if(!enc->codec_tag)
return -1;
}
end_header(pb, hpos);
/* patch the header size fields */
cur_pos = url_ftell(pb);
header_size = cur_pos - header_offset;
if (asf->is_streamed) {
header_size += 8 + 30 + 50;
url_fseek(pb, header_offset - 10 - 30, SEEK_SET);
put_le16(pb, header_size);
url_fseek(pb, header_offset - 2 - 30, SEEK_SET);
put_le16(pb, header_size);
header_size -= 8 + 30 + 50;
}
header_size += 24 + 6;
url_fseek(pb, header_offset - 14, SEEK_SET);
put_le64(pb, header_size);
url_fseek(pb, cur_pos, SEEK_SET);
/* movie chunk, followed by packets of packet_size */
asf->data_offset = cur_pos;
put_guid(pb, &data_header);
put_le64(pb, data_chunk_size);
put_guid(pb, &my_guid);
put_le64(pb, asf->nb_packets); /* nb packets */
put_byte(pb, 1); /* ??? */
put_byte(pb, 1); /* ??? */
return 0;
}
static int asf_write_header(AVFormatContext *s)
{
ASFContext *asf = s->priv_data;
asf->packet_size = PACKET_SIZE;
asf->nb_packets = 0;
asf->last_indexed_pts = 0;
asf->index_ptr = (ASFIndex*)av_malloc( sizeof(ASFIndex) * ASF_INDEX_BLOCK );
asf->nb_index_memory_alloc = ASF_INDEX_BLOCK;
asf->nb_index_count = 0;
asf->maximum_packet = 0;
if (asf_write_header1(s, 0, 0) < 0) {
//av_free(asf);
return -1;
}
put_flush_packet(&s->pb);
asf->packet_nb_payloads = 0;
asf->packet_timestamp_start = -1;
asf->packet_timestamp_end = -1;
init_put_byte(&asf->pb, asf->packet_buf, asf->packet_size, 1,
NULL, NULL, NULL, NULL);
return 0;
}
static int asf_write_stream_header(AVFormatContext *s)
{
ASFContext *asf = s->priv_data;
asf->is_streamed = 1;
return asf_write_header(s);
}
static int put_payload_parsing_info(
AVFormatContext *s,
unsigned int sendtime,
unsigned int duration,
int nb_payloads,
int padsize
)
{
ASFContext *asf = s->priv_data;
ByteIOContext *pb = &s->pb;
int ppi_size, i;
int64_t start= url_ftell(pb);
int iLengthTypeFlags = ASF_PPI_LENGTH_TYPE_FLAGS;
padsize -= PACKET_HEADER_MIN_SIZE;
if(asf->multi_payloads_present)
padsize--;
assert(padsize>=0);
put_byte(pb, ASF_PACKET_ERROR_CORRECTION_FLAGS);
for (i = 0; i < ASF_PACKET_ERROR_CORRECTION_DATA_SIZE; i++){
put_byte(pb, 0x0);
}
if (asf->multi_payloads_present)
iLengthTypeFlags |= ASF_PPI_FLAG_MULTIPLE_PAYLOADS_PRESENT;
if (padsize > 0) {
if (padsize < 256)
iLengthTypeFlags |= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE;
else
iLengthTypeFlags |= ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD;
}
put_byte(pb, iLengthTypeFlags);
put_byte(pb, ASF_PPI_PROPERTY_FLAGS);
if (iLengthTypeFlags & ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_WORD)
put_le16(pb, padsize - 2);
if (iLengthTypeFlags & ASF_PPI_FLAG_PADDING_LENGTH_FIELD_IS_BYTE)
put_byte(pb, padsize - 1);
put_le32(pb, sendtime);
put_le16(pb, duration);
if (asf->multi_payloads_present)
put_byte(pb, nb_payloads | ASF_PAYLOAD_FLAGS);
ppi_size = url_ftell(pb) - start;
return ppi_size;
}
static void flush_packet(AVFormatContext *s)
{
ASFContext *asf = s->priv_data;
int packet_hdr_size, packet_filled_size;
if (asf->is_streamed) {
put_chunk(s, 0x4424, asf->packet_size, 0);
}
packet_hdr_size = put_payload_parsing_info(
s,
asf->packet_timestamp_start,
asf->packet_timestamp_end - asf->packet_timestamp_start,
asf->packet_nb_payloads,
asf->packet_size_left
);
packet_filled_size = PACKET_SIZE - asf->packet_size_left;
assert(packet_hdr_size <= asf->packet_size_left);
memset(asf->packet_buf + packet_filled_size, 0, asf->packet_size_left);
put_buffer(&s->pb, asf->packet_buf, asf->packet_size - packet_hdr_size);
put_flush_packet(&s->pb);
asf->nb_packets++;
asf->packet_nb_payloads = 0;
asf->packet_timestamp_start = -1;
asf->packet_timestamp_end = -1;
init_put_byte(&asf->pb, asf->packet_buf, asf->packet_size, 1,
NULL, NULL, NULL, NULL);
}
static void put_payload_header(
AVFormatContext *s,
ASFStream *stream,
int presentation_time,
int m_obj_size,
int m_obj_offset,
int payload_len,
int flags
)
{
ASFContext *asf = s->priv_data;
ByteIOContext *pb = &asf->pb;
int val;
val = stream->num;
if (flags & PKT_FLAG_KEY)
val |= ASF_PL_FLAG_KEY_FRAME;
put_byte(pb, val);
put_byte(pb, stream->seq); //Media object number
put_le32(pb, m_obj_offset); //Offset Into Media Object
// Replicated Data shall be at least 8 bytes long.
// The first 4 bytes of data shall contain the
// Size of the Media Object that the payload belongs to.
// The next 4 bytes of data shall contain the
// Presentation Time for the media object that the payload belongs to.
put_byte(pb, ASF_PAYLOAD_REPLICATED_DATA_LENGTH);
put_le32(pb, m_obj_size); //Replicated Data - Media Object Size
put_le32(pb, presentation_time);//Replicated Data - Presentation Time
if (asf->multi_payloads_present){
put_le16(pb, payload_len); //payload length
}
}
static void put_frame(
AVFormatContext *s,
ASFStream *stream,
AVStream *avst,
int timestamp,
const uint8_t *buf,
int m_obj_size,
int flags
)
{
ASFContext *asf = s->priv_data;
int m_obj_offset, payload_len, frag_len1;
m_obj_offset = 0;
while (m_obj_offset < m_obj_size) {
payload_len = m_obj_size - m_obj_offset;
if (asf->packet_timestamp_start == -1) {
asf->multi_payloads_present = (payload_len < MULTI_PAYLOAD_CONSTANT);
asf->packet_size_left = PACKET_SIZE;
if (asf->multi_payloads_present){
frag_len1 = MULTI_PAYLOAD_CONSTANT - 1;
}
else {
frag_len1 = SINGLE_PAYLOAD_DATA_LENGTH;
}
asf->packet_timestamp_start = timestamp;
}
else {
// multi payloads
frag_len1 = asf->packet_size_left - PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS - PACKET_HEADER_MIN_SIZE - 1;
asf->packet_timestamp_start = timestamp;
if(frag_len1 < payload_len && avst->codec->codec_type == CODEC_TYPE_AUDIO){
flush_packet(s);
continue;
}
}
if (frag_len1 > 0) {
if (payload_len > frag_len1)
payload_len = frag_len1;
else if (payload_len == (frag_len1 - 1))
payload_len = frag_len1 - 2; //additional byte need to put padding length
put_payload_header(s, stream, timestamp+PREROLL_TIME, m_obj_size, m_obj_offset, payload_len, flags);
put_buffer(&asf->pb, buf, payload_len);
if (asf->multi_payloads_present)
asf->packet_size_left -= (payload_len + PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS);
else
asf->packet_size_left -= (payload_len + PAYLOAD_HEADER_SIZE_SINGLE_PAYLOAD);
asf->packet_timestamp_end = timestamp;
asf->packet_nb_payloads++;
} else {
payload_len = 0;
}
m_obj_offset += payload_len;
buf += payload_len;
if (!asf->multi_payloads_present)
flush_packet(s);
else if (asf->packet_size_left <= (PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS + PACKET_HEADER_MIN_SIZE + 1))
flush_packet(s);
}
stream->seq++;
}
static int asf_write_packet(AVFormatContext *s, AVPacket *pkt)
{
ASFContext *asf = s->priv_data;
ASFStream *stream;
int64_t duration;
AVCodecContext *codec;
int64_t packet_st,pts;
int start_sec,i;
int flags= pkt->flags;
codec = s->streams[pkt->stream_index]->codec;
stream = &asf->streams[pkt->stream_index];
if(codec->codec_type == CODEC_TYPE_AUDIO)
flags &= ~PKT_FLAG_KEY;
//XXX /FIXME use duration from AVPacket (quick hack by)
pts = (pkt->pts != AV_NOPTS_VALUE) ? pkt->pts : pkt->dts;
assert(pts != AV_NOPTS_VALUE);
duration = pts * 10000;
asf->duration= FFMAX(asf->duration, duration);
packet_st = asf->nb_packets;
put_frame(s, stream, s->streams[pkt->stream_index], pkt->dts, pkt->data, pkt->size, flags);
/* check index */
if ((!asf->is_streamed) && (flags & PKT_FLAG_KEY)) {
start_sec = (int)(duration / INT64_C(10000000));
if (start_sec != (int)(asf->last_indexed_pts / INT64_C(10000000))) {
for(i=asf->nb_index_count;i<start_sec;i++) {
if (i>=asf->nb_index_memory_alloc) {
asf->nb_index_memory_alloc += ASF_INDEX_BLOCK;
asf->index_ptr = (ASFIndex*)av_realloc( asf->index_ptr, sizeof(ASFIndex) * asf->nb_index_memory_alloc );
}
// store
asf->index_ptr[i].packet_number = (uint32_t)packet_st;
asf->index_ptr[i].packet_count = (uint16_t)(asf->nb_packets-packet_st);
asf->maximum_packet = FFMAX(asf->maximum_packet, (uint16_t)(asf->nb_packets-packet_st));
}
asf->nb_index_count = start_sec;
asf->last_indexed_pts = duration;
}
}
return 0;
}
//
static int asf_write_index(AVFormatContext *s, ASFIndex *index, uint16_t max, uint32_t count)
{
ByteIOContext *pb = &s->pb;
int i;
put_guid(pb, &simple_index_header);
put_le64(pb, 24 + 16 + 8 + 4 + 4 + (4 + 2)*count);
put_guid(pb, &my_guid);
put_le64(pb, ASF_INDEXED_INTERVAL);
put_le32(pb, max);
put_le32(pb, count);
for(i=0; i<count; i++) {
put_le32(pb, index[i].packet_number);
put_le16(pb, index[i].packet_count);
}
return 0;
}
static int asf_write_trailer(AVFormatContext *s)
{
ASFContext *asf = s->priv_data;
int64_t file_size,data_size;
/* flush the current packet */
if (asf->pb.buf_ptr > asf->pb.buffer)
flush_packet(s);
/* write index */
data_size = url_ftell(&s->pb);
if ((!asf->is_streamed) && (asf->nb_index_count != 0)) {
asf_write_index(s, asf->index_ptr, asf->maximum_packet, asf->nb_index_count);
}
put_flush_packet(&s->pb);
if (asf->is_streamed || url_is_streamed(&s->pb)) {
put_chunk(s, 0x4524, 0, 0); /* end of stream */
} else {
/* rewrite an updated header */
file_size = url_ftell(&s->pb);
url_fseek(&s->pb, 0, SEEK_SET);
asf_write_header1(s, file_size, data_size - asf->data_offset);
}
put_flush_packet(&s->pb);
av_free(asf->index_ptr);
return 0;
}
#ifdef CONFIG_ASF_MUXER
AVOutputFormat asf_muxer = {
"asf",
"asf format",
"video/x-ms-asf",
"asf,wmv,wma",
sizeof(ASFContext),
#ifdef CONFIG_LIBMP3LAME
CODEC_ID_MP3,
#else
CODEC_ID_MP2,
#endif
CODEC_ID_MSMPEG4V3,
asf_write_header,
asf_write_packet,
asf_write_trailer,
.flags = AVFMT_GLOBALHEADER,
.codec_tag= (const AVCodecTag*[]){codec_asf_bmp_tags, codec_bmp_tags, codec_wav_tags, 0},
};
#endif
#ifdef CONFIG_ASF_STREAM_MUXER
AVOutputFormat asf_stream_muxer = {
"asf_stream",
"asf format",
"video/x-ms-asf",
"asf,wmv,wma",
sizeof(ASFContext),
#ifdef CONFIG_LIBMP3LAME
CODEC_ID_MP3,
#else
CODEC_ID_MP2,
#endif
CODEC_ID_MSMPEG4V3,
asf_write_stream_header,
asf_write_packet,
asf_write_trailer,
.flags = AVFMT_GLOBALHEADER,
.codec_tag= (const AVCodecTag*[]){codec_asf_bmp_tags, codec_bmp_tags, codec_wav_tags, 0},
};
#endif //CONFIG_ASF_STREAM_MUXER
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -