diff options
Diffstat (limited to 'libavformat/asfenc.c')
-rw-r--r-- | libavformat/asfenc.c | 141 |
1 files changed, 81 insertions, 60 deletions
diff --git a/libavformat/asfenc.c b/libavformat/asfenc.c index a523b3a..f3aec9c 100644 --- a/libavformat/asfenc.c +++ b/libavformat/asfenc.c @@ -2,20 +2,20 @@ * ASF muxer * Copyright (c) 2000, 2001 Fabrice Bellard * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -31,7 +31,7 @@ #define ASF_INDEXED_INTERVAL 10000000 -#define ASF_INDEX_BLOCK 600 +#define ASF_INDEX_BLOCK (1<<9) #define ASF_PACKET_ERROR_CORRECTION_DATA_SIZE 0x2 #define ASF_PACKET_ERROR_CORRECTION_FLAGS \ @@ -192,31 +192,33 @@ typedef struct { /* packet filling */ unsigned char multi_payloads_present; int packet_size_left; - int packet_timestamp_start; - int packet_timestamp_end; + int64_t packet_timestamp_start; + int64_t packet_timestamp_end; unsigned int packet_nb_payloads; uint8_t packet_buf[PACKET_SIZE]; AVIOContext pb; /* only for reading */ uint64_t data_offset; ///< beginning of the first data packet - int64_t last_indexed_pts; ASFIndex *index_ptr; - uint32_t nb_index_count; uint32_t nb_index_memory_alloc; uint16_t maximum_packet; + uint32_t next_packet_number; + uint16_t next_packet_count; + int next_start_sec; + int end_sec; } ASFContext; static const AVCodecTag codec_asf_bmp_tags[] = { - { AV_CODEC_ID_MPEG4, MKTAG('M', 'P', '4', 'S') }, { AV_CODEC_ID_MPEG4, MKTAG('M', '4', 'S', '2') }, + { AV_CODEC_ID_MPEG4, MKTAG('M', 'P', '4', 'S') }, { AV_CODEC_ID_MSMPEG4V3, MKTAG('M', 'P', '4', '3') }, { AV_CODEC_ID_NONE, 0 }, }; #define PREROLL_TIME 3100 -static void put_guid(AVIOContext *s, const ff_asf_guid *g) +void ff_put_guid(AVIOContext *s, const ff_asf_guid *g) { assert(sizeof(*g) == 16); avio_write(s, *g, sizeof(*g)); @@ -242,7 +244,7 @@ static int64_t put_header(AVIOContext *pb, const ff_asf_guid *g) int64_t pos; pos = avio_tell(pb); - put_guid(pb, g); + ff_put_guid(pb, g); avio_wl64(pb, 24); return pos; } @@ -325,7 +327,7 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, put_chunk(s, 0x4824, 0, 0xc00); /* start of stream (length will be patched later) */ } - put_guid(pb, &ff_asf_header); + ff_put_guid(pb, &ff_asf_header); avio_wl64(pb, -1); /* header length, will be patched after */ avio_wl32(pb, 3 + has_title + !!metadata_count + s->nb_streams); /* number of chunks in header */ avio_w8(pb, 1); /* ??? */ @@ -334,7 +336,7 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, /* file header */ header_offset = avio_tell(pb); hpos = put_header(pb, &ff_asf_file_header); - put_guid(pb, &ff_asf_my_guid); + ff_put_guid(pb, &ff_asf_my_guid); avio_wl64(pb, file_size); file_time = 0; avio_wl64(pb, unix_to_file_time(file_time)); @@ -350,7 +352,7 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, /* unknown headers */ hpos = put_header(pb, &ff_asf_head1_guid); - put_guid(pb, &ff_asf_head2_guid); + ff_put_guid(pb, &ff_asf_head2_guid); avio_wl32(pb, 6); avio_wl16(pb, 0); end_header(pb, hpos); @@ -394,7 +396,7 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, enc = s->streams[n]->codec; asf->streams[n].num = n + 1; - asf->streams[n].seq = 0; + asf->streams[n].seq = 1; switch (enc->codec_type) { case AVMEDIA_TYPE_AUDIO: @@ -412,11 +414,11 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, hpos = put_header(pb, &ff_asf_stream_header); if (enc->codec_type == AVMEDIA_TYPE_AUDIO) { - put_guid(pb, &ff_asf_audio_stream); - put_guid(pb, &ff_asf_audio_conceal_spread); + ff_put_guid(pb, &ff_asf_audio_stream); + ff_put_guid(pb, &ff_asf_audio_conceal_spread); } else { - put_guid(pb, &ff_asf_video_stream); - put_guid(pb, &ff_asf_video_conceal_none); + ff_put_guid(pb, &ff_asf_video_stream); + ff_put_guid(pb, &ff_asf_video_conceal_none); } avio_wl64(pb, 0); /* ??? */ es_pos = avio_tell(pb); @@ -463,7 +465,7 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, /* media comments */ hpos = put_header(pb, &ff_asf_codec_comment_header); - put_guid(pb, &ff_asf_codec_comment1_header); + ff_put_guid(pb, &ff_asf_codec_comment1_header); avio_wl32(pb, s->nb_streams); for (n = 0; n < s->nb_streams; n++) { AVCodec *p; @@ -533,9 +535,9 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, /* movie chunk, followed by packets of packet_size */ asf->data_offset = cur_pos; - put_guid(pb, &ff_asf_data_header); + ff_put_guid(pb, &ff_asf_data_header); avio_wl64(pb, data_chunk_size); - put_guid(pb, &ff_asf_my_guid); + ff_put_guid(pb, &ff_asf_my_guid); avio_wl64(pb, asf->nb_packets); /* nb packets */ avio_w8(pb, 1); /* ??? */ avio_w8(pb, 1); /* ??? */ @@ -549,10 +551,8 @@ static int asf_write_header(AVFormatContext *s) s->packet_size = PACKET_SIZE; asf->nb_packets = 0; - asf->last_indexed_pts = 0; asf->index_ptr = av_malloc(sizeof(ASFIndex) * ASF_INDEX_BLOCK); asf->nb_index_memory_alloc = ASF_INDEX_BLOCK; - asf->nb_index_count = 0; asf->maximum_packet = 0; /* the data-chunk-size has to be 50, which is data_size - asf->data_offset @@ -571,6 +571,9 @@ static int asf_write_header(AVFormatContext *s) ffio_init_context(&asf->pb, asf->packet_buf, s->packet_size, 1, NULL, NULL, NULL, NULL); + if (s->avoid_negative_ts < 0) + s->avoid_negative_ts = 1; + return 0; } @@ -643,8 +646,7 @@ static void flush_packet(AVFormatContext *s) packet_hdr_size = put_payload_parsing_info(s, asf->packet_timestamp_start, - asf->packet_timestamp_end - - asf->packet_timestamp_start, + asf->packet_timestamp_end - asf->packet_timestamp_start, asf->packet_nb_payloads, asf->packet_size_left); @@ -664,7 +666,7 @@ static void flush_packet(AVFormatContext *s) } static void put_payload_header(AVFormatContext *s, ASFStream *stream, - int presentation_time, int m_obj_size, + int64_t presentation_time, int m_obj_size, int m_obj_offset, int payload_len, int flags) { ASFContext *asf = s->priv_data; @@ -687,7 +689,7 @@ static void put_payload_header(AVFormatContext *s, ASFStream *stream, avio_w8(pb, ASF_PAYLOAD_REPLICATED_DATA_LENGTH); avio_wl32(pb, m_obj_size); // Replicated Data - Media Object Size - avio_wl32(pb, presentation_time); // Replicated Data - Presentation Time + avio_wl32(pb, (uint32_t) presentation_time); // Replicated Data - Presentation Time if (asf->multi_payloads_present) { avio_wl16(pb, payload_len); // payload length @@ -695,7 +697,7 @@ static void put_payload_header(AVFormatContext *s, ASFStream *stream, } static void put_frame(AVFormatContext *s, ASFStream *stream, AVStream *avst, - int timestamp, const uint8_t *buf, + int64_t timestamp, const uint8_t *buf, int m_obj_size, int flags) { ASFContext *asf = s->priv_data; @@ -757,14 +759,42 @@ static void put_frame(AVFormatContext *s, ASFStream *stream, AVStream *avst, stream->seq++; } +static void update_index(AVFormatContext *s, int start_sec, + uint32_t packet_number, uint16_t packet_count) +{ + ASFContext *asf = s->priv_data; + + if (start_sec > asf->next_start_sec) { + int i; + + if (!asf->next_start_sec) { + asf->next_packet_number = packet_number; + asf->next_packet_count = packet_count; + } + + if (start_sec > asf->nb_index_memory_alloc) { + asf->nb_index_memory_alloc = (start_sec + ASF_INDEX_BLOCK) & ~(ASF_INDEX_BLOCK - 1); + asf->index_ptr = av_realloc( asf->index_ptr, sizeof(ASFIndex) * asf->nb_index_memory_alloc ); + } + for (i = asf->next_start_sec; i < start_sec; i++) { + asf->index_ptr[i].packet_number = asf->next_packet_number; + asf->index_ptr[i].packet_count = asf->next_packet_count; + } + } + asf->maximum_packet = FFMAX(asf->maximum_packet, packet_count); + asf->next_packet_number = packet_number; + asf->next_packet_count = packet_count; + asf->next_start_sec = start_sec; +} + 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; + uint32_t packet_number; + int64_t pts; + int start_sec; int flags = pkt->flags; codec = s->streams[pkt->stream_index]->codec; @@ -775,34 +805,23 @@ static int asf_write_packet(AVFormatContext *s, AVPacket *pkt) pts = (pkt->pts != AV_NOPTS_VALUE) ? pkt->pts : pkt->dts; assert(pts != AV_NOPTS_VALUE); - duration = pts * 10000; - asf->duration = FFMAX(asf->duration, duration + pkt->duration * 10000); + pts *= 10000; + asf->duration = FFMAX(asf->duration, pts + pkt->duration * 10000); - packet_st = asf->nb_packets; + packet_number = asf->nb_packets; put_frame(s, stream, s->streams[pkt->stream_index], pkt->dts, pkt->data, pkt->size, flags); + start_sec = (int)((PREROLL_TIME * 10000 + pts + ASF_INDEXED_INTERVAL - 1) + / ASF_INDEXED_INTERVAL); + /* check index */ if ((!asf->is_streamed) && (flags & AV_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; - } + uint16_t packet_count = asf->nb_packets - packet_number; + update_index(s, start_sec, packet_number, packet_count); } + asf->end_sec = start_sec; + return 0; } @@ -812,9 +831,9 @@ static int asf_write_index(AVFormatContext *s, ASFIndex *index, AVIOContext *pb = s->pb; int i; - put_guid(pb, &ff_asf_simple_index_header); + ff_put_guid(pb, &ff_asf_simple_index_header); avio_wl64(pb, 24 + 16 + 8 + 4 + 4 + (4 + 2) * count); - put_guid(pb, &ff_asf_my_guid); + ff_put_guid(pb, &ff_asf_my_guid); avio_wl64(pb, ASF_INDEXED_INTERVAL); avio_wl32(pb, max); avio_wl32(pb, count); @@ -837,8 +856,10 @@ static int asf_write_trailer(AVFormatContext *s) /* write index */ data_size = avio_tell(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); + if (!asf->is_streamed && asf->next_start_sec) { + update_index(s, asf->end_sec + 1, 0, 0); + asf_write_index(s, asf->index_ptr, asf->maximum_packet, asf->next_start_sec); + } avio_flush(s->pb); if (asf->is_streamed || !s->pb->seekable) { @@ -861,7 +882,7 @@ AVOutputFormat ff_asf_muxer = { .mime_type = "video/x-ms-asf", .extensions = "asf,wmv,wma", .priv_data_size = sizeof(ASFContext), - .audio_codec = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_MP2, + .audio_codec = AV_CODEC_ID_WMAV2, .video_codec = AV_CODEC_ID_MSMPEG4V3, .write_header = asf_write_header, .write_packet = asf_write_packet, @@ -880,7 +901,7 @@ AVOutputFormat ff_asf_stream_muxer = { .mime_type = "video/x-ms-asf", .extensions = "asf,wmv,wma", .priv_data_size = sizeof(ASFContext), - .audio_codec = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_MP2, + .audio_codec = AV_CODEC_ID_WMAV2, .video_codec = AV_CODEC_ID_MSMPEG4V3, .write_header = asf_write_stream_header, .write_packet = asf_write_packet, |