diff options
| author | Tim Redfern <tim@eclectronics.org> | 2013-12-29 12:19:38 +0000 |
|---|---|---|
| committer | Tim Redfern <tim@eclectronics.org> | 2013-12-29 12:19:38 +0000 |
| commit | f7813a5324be39d13ab536c245d15dfc602a7849 (patch) | |
| tree | fad99148b88823d34a5df2f0a25881a002eb291b /ffmpeg/libavformat/asfenc.c | |
| parent | b7a5a477b8ff4d4e3028b9dfb9a9df0a41463f92 (diff) | |
basic type mechanism working
Diffstat (limited to 'ffmpeg/libavformat/asfenc.c')
| -rw-r--r-- | ffmpeg/libavformat/asfenc.c | 127 |
1 files changed, 108 insertions, 19 deletions
diff --git a/ffmpeg/libavformat/asfenc.c b/ffmpeg/libavformat/asfenc.c index f3aec9c..8e343b3 100644 --- a/ffmpeg/libavformat/asfenc.c +++ b/ffmpeg/libavformat/asfenc.c @@ -19,7 +19,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/avassert.h" #include "libavutil/dict.h" +#include "libavutil/mathematics.h" #include "avformat.h" #include "avio_internal.h" #include "internal.h" @@ -182,6 +184,8 @@ 1 - /* Payload Flags */ \ 2 * PAYLOAD_HEADER_SIZE_MULTIPLE_PAYLOADS) +#define DATA_HEADER_SIZE 50 + typedef struct { uint32_t seqno; int is_streamed; @@ -205,6 +209,7 @@ typedef struct { uint16_t maximum_packet; uint32_t next_packet_number; uint16_t next_packet_count; + uint64_t next_packet_offset; int next_start_sec; int end_sec; } ASFContext; @@ -220,7 +225,7 @@ static const AVCodecTag codec_asf_bmp_tags[] = { void ff_put_guid(AVIOContext *s, const ff_asf_guid *g) { - assert(sizeof(*g) == 16); + av_assert0(sizeof(*g) == 16); avio_write(s, *g, sizeof(*g)); } @@ -287,6 +292,64 @@ static int64_t unix_to_file_time(int ti) return t; } +static int32_t get_send_time(ASFContext *asf, int64_t pres_time, uint64_t *offset) +{ + int i; + int32_t send_time = 0; + *offset = asf->data_offset + DATA_HEADER_SIZE; + for (i = 0; i < asf->next_start_sec; i++) { + if (pres_time <= asf->index_ptr[i].send_time) + break; + send_time = asf->index_ptr[i].send_time; + *offset = asf->index_ptr[i].offset; + } + + return send_time / 10000; +} + +static int asf_write_markers(AVFormatContext *s) +{ + ASFContext *asf = s->priv_data; + AVIOContext *pb = s->pb; + int i; + AVRational scale = {1, 10000000}; + int64_t hpos = put_header(pb, &ff_asf_marker_header); + + ff_put_guid(pb, &ff_asf_reserved_4);// ASF spec mandates this reserved value + avio_wl32(pb, s->nb_chapters); // markers count + avio_wl16(pb, 0); // ASF spec mandates 0 for this + avio_wl16(pb, 0); // name length 0, no name given + + for (i = 0; i < s->nb_chapters; i++) { + AVChapter *c = s->chapters[i]; + AVDictionaryEntry *t = av_dict_get(c->metadata, "title", NULL, 0); + int64_t pres_time = av_rescale_q(c->start, c->time_base, scale); + uint64_t offset; + int32_t send_time = get_send_time(asf, pres_time, &offset); + int len = 0; + uint8_t *buf; + AVIOContext *dyn_buf; + if (t) { + if (avio_open_dyn_buf(&dyn_buf) < 0) + return AVERROR(ENOMEM); + avio_put_str16le(dyn_buf, t->value); + len = avio_close_dyn_buf(dyn_buf, &buf); + } + avio_wl64(pb, offset); // offset of the packet with send_time + avio_wl64(pb, pres_time + PREROLL_TIME * 10000); // presentation time + avio_wl16(pb, 12 + len); // entry length + avio_wl32(pb, send_time); // send time + avio_wl32(pb, 0); // flags, should be 0 + avio_wl32(pb, len / 2); // marker desc length in WCHARS! + if (t) { + avio_write(pb, buf, len); // marker desc + av_freep(&buf); + } + } + end_header(pb, hpos); + return 0; +} + /* 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) @@ -388,7 +451,12 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, } end_header(pb, hpos); } - + /* chapters using ASF markers */ + if (!asf->is_streamed && s->nb_chapters) { + int ret; + if (ret = asf_write_markers(s)) + return ret; + } /* stream headers */ for (n = 0; n < s->nb_streams; n++) { int64_t es_pos; @@ -457,7 +525,7 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, avio_wl16(pb, 40 + enc->extradata_size); /* size */ /* BITMAPINFOHEADER header */ - ff_put_bmp_header(pb, enc, ff_codec_bmp_tags, 1); + ff_put_bmp_header(pb, enc, ff_codec_bmp_tags, 1, 0); } end_header(pb, hpos); } @@ -519,14 +587,14 @@ static int asf_write_header1(AVFormatContext *s, int64_t file_size, cur_pos = avio_tell(pb); header_size = cur_pos - header_offset; if (asf->is_streamed) { - header_size += 8 + 30 + 50; + header_size += 8 + 30 + DATA_HEADER_SIZE; avio_seek(pb, header_offset - 10 - 30, SEEK_SET); avio_wl16(pb, header_size); avio_seek(pb, header_offset - 2 - 30, SEEK_SET); avio_wl16(pb, header_size); - header_size -= 8 + 30 + 50; + header_size -= 8 + 30 + DATA_HEADER_SIZE; } header_size += 24 + 6; avio_seek(pb, header_offset - 14, SEEK_SET); @@ -555,10 +623,10 @@ static int asf_write_header(AVFormatContext *s) asf->nb_index_memory_alloc = ASF_INDEX_BLOCK; asf->maximum_packet = 0; - /* the data-chunk-size has to be 50, which is data_size - asf->data_offset - * at the moment this function is done. It is needed to use asf as - * streamable format. */ - if (asf_write_header1(s, 0, 50) < 0) { + /* the data-chunk-size has to be 50 (DATA_HEADER_SIZE), which is + * data_size - asf->data_offset at the moment this function is done. + * It is needed to use asf as a streamable format. */ + if (asf_write_header1(s, 0, DATA_HEADER_SIZE) < 0) { //av_free(asf); return -1; } @@ -600,7 +668,7 @@ static int put_payload_parsing_info(AVFormatContext *s, padsize -= PACKET_HEADER_MIN_SIZE; if (asf->multi_payloads_present) padsize--; - assert(padsize >= 0); + av_assert0(padsize >= 0); avio_w8(pb, ASF_PACKET_ERROR_CORRECTION_FLAGS); for (i = 0; i < ASF_PACKET_ERROR_CORRECTION_DATA_SIZE; i++) @@ -639,7 +707,7 @@ static void flush_packet(AVFormatContext *s) ASFContext *asf = s->priv_data; int packet_hdr_size, packet_filled_size; - assert(asf->packet_timestamp_end >= asf->packet_timestamp_start); + av_assert0(asf->packet_timestamp_end >= asf->packet_timestamp_start); if (asf->is_streamed) put_chunk(s, 0x4424, s->packet_size, 0); @@ -651,7 +719,7 @@ static void flush_packet(AVFormatContext *s) asf->packet_size_left); packet_filled_size = PACKET_SIZE - asf->packet_size_left; - assert(packet_hdr_size <= asf->packet_size_left); + av_assert0(packet_hdr_size <= asf->packet_size_left); memset(asf->packet_buf + packet_filled_size, 0, asf->packet_size_left); avio_write(s->pb, asf->packet_buf, s->packet_size - packet_hdr_size); @@ -759,8 +827,9 @@ 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) +static int update_index(AVFormatContext *s, int start_sec, + uint32_t packet_number, uint16_t packet_count, + uint64_t packet_offset) { ASFContext *asf = s->priv_data; @@ -770,32 +839,48 @@ static void update_index(AVFormatContext *s, int start_sec, if (!asf->next_start_sec) { asf->next_packet_number = packet_number; asf->next_packet_count = packet_count; + asf->next_packet_offset = packet_offset; } if (start_sec > asf->nb_index_memory_alloc) { + int err; 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 ); + if ((err = av_reallocp_array(&asf->index_ptr, + asf->nb_index_memory_alloc, + sizeof(*asf->index_ptr))) < 0) { + asf->nb_index_memory_alloc = 0; + return err; + } } 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->index_ptr[i].send_time = asf->next_start_sec * INT64_C(10000000); + asf->index_ptr[i].offset = asf->next_packet_offset; + } } asf->maximum_packet = FFMAX(asf->maximum_packet, packet_count); asf->next_packet_number = packet_number; asf->next_packet_count = packet_count; + asf->next_packet_offset = packet_offset; asf->next_start_sec = start_sec; + + return 0; } static int asf_write_packet(AVFormatContext *s, AVPacket *pkt) { ASFContext *asf = s->priv_data; + AVIOContext *pb = s->pb; ASFStream *stream; AVCodecContext *codec; uint32_t packet_number; int64_t pts; int start_sec; int flags = pkt->flags; + int ret; + uint64_t offset = avio_tell(pb); codec = s->streams[pkt->stream_index]->codec; stream = &asf->streams[pkt->stream_index]; @@ -804,7 +889,7 @@ static int asf_write_packet(AVFormatContext *s, AVPacket *pkt) flags &= ~AV_PKT_FLAG_KEY; pts = (pkt->pts != AV_NOPTS_VALUE) ? pkt->pts : pkt->dts; - assert(pts != AV_NOPTS_VALUE); + av_assert0(pts != AV_NOPTS_VALUE); pts *= 10000; asf->duration = FFMAX(asf->duration, pts + pkt->duration * 10000); @@ -818,7 +903,9 @@ static int asf_write_packet(AVFormatContext *s, AVPacket *pkt) /* check index */ if ((!asf->is_streamed) && (flags & AV_PKT_FLAG_KEY)) { uint16_t packet_count = asf->nb_packets - packet_number; - update_index(s, start_sec, packet_number, packet_count); + ret = update_index(s, start_sec, packet_number, packet_count, offset); + if (ret < 0) + return ret; } asf->end_sec = start_sec; @@ -849,6 +936,7 @@ static int asf_write_trailer(AVFormatContext *s) { ASFContext *asf = s->priv_data; int64_t file_size, data_size; + int ret; /* flush the current packet */ if (asf->pb.buf_ptr > asf->pb.buffer) @@ -857,7 +945,8 @@ static int asf_write_trailer(AVFormatContext *s) /* write index */ data_size = avio_tell(s->pb); if (!asf->is_streamed && asf->next_start_sec) { - update_index(s, asf->end_sec + 1, 0, 0); + if ((ret = update_index(s, asf->end_sec + 1, 0, 0, 0)) < 0) + return ret; asf_write_index(s, asf->index_ptr, asf->maximum_packet, asf->next_start_sec); } avio_flush(s->pb); @@ -871,7 +960,7 @@ static int asf_write_trailer(AVFormatContext *s) asf_write_header1(s, file_size, data_size - asf->data_offset); } - av_free(asf->index_ptr); + av_freep(&asf->index_ptr); return 0; } |
