comparison matroskaenc.c @ 5793:640f14283092 libavformat

mkvenc: write dts for VFW mode
author conrad
date Tue, 09 Mar 2010 04:23:28 +0000
parents 551765b1772b
children 31e8a43123c5
comparison
equal deleted inserted replaced
5792:2fb291f12e5f 5793:640f14283092
59 int64_t segment_offset; 59 int64_t segment_offset;
60 mkv_cuepoint *entries; 60 mkv_cuepoint *entries;
61 int num_entries; 61 int num_entries;
62 } mkv_cues; 62 } mkv_cues;
63 63
64 typedef struct {
65 int write_dts;
66 } mkv_track;
67
64 typedef struct MatroskaMuxContext { 68 typedef struct MatroskaMuxContext {
65 ByteIOContext *dyn_bc; 69 ByteIOContext *dyn_bc;
66 ebml_master segment; 70 ebml_master segment;
67 int64_t segment_offset; 71 int64_t segment_offset;
68 int64_t segment_uid; 72 int64_t segment_uid;
72 int64_t duration_offset; 76 int64_t duration_offset;
73 uint64_t duration; 77 uint64_t duration;
74 mkv_seekhead *main_seekhead; 78 mkv_seekhead *main_seekhead;
75 mkv_seekhead *cluster_seekhead; 79 mkv_seekhead *cluster_seekhead;
76 mkv_cues *cues; 80 mkv_cues *cues;
81 mkv_track *tracks;
77 82
78 struct AVMD5 *md5_ctx; 83 struct AVMD5 *md5_ctx;
79 } MatroskaMuxContext; 84 } MatroskaMuxContext;
80 85
81 86
340 345
341 cues->segment_offset = segment_offset; 346 cues->segment_offset = segment_offset;
342 return cues; 347 return cues;
343 } 348 }
344 349
345 static int mkv_add_cuepoint(mkv_cues *cues, AVPacket *pkt, int64_t cluster_pos) 350 static int mkv_add_cuepoint(mkv_cues *cues, int stream, int64_t ts, int64_t cluster_pos)
346 { 351 {
347 mkv_cuepoint *entries = cues->entries; 352 mkv_cuepoint *entries = cues->entries;
348 353
349 entries = av_realloc(entries, (cues->num_entries + 1) * sizeof(mkv_cuepoint)); 354 entries = av_realloc(entries, (cues->num_entries + 1) * sizeof(mkv_cuepoint));
350 if (entries == NULL) 355 if (entries == NULL)
351 return AVERROR(ENOMEM); 356 return AVERROR(ENOMEM);
352 357
353 entries[cues->num_entries ].pts = pkt->pts; 358 entries[cues->num_entries ].pts = ts;
354 entries[cues->num_entries ].tracknum = pkt->stream_index + 1; 359 entries[cues->num_entries ].tracknum = stream + 1;
355 entries[cues->num_entries++].cluster_pos = cluster_pos - cues->segment_offset; 360 entries[cues->num_entries++].cluster_pos = cluster_pos - cues->segment_offset;
356 361
357 cues->entries = entries; 362 cues->entries = entries;
358 return 0; 363 return 0;
359 } 364 }
566 || codec->codec_id == CODEC_ID_CINEPAK)) 571 || codec->codec_id == CODEC_ID_CINEPAK))
567 qt_id = 1; 572 qt_id = 1;
568 573
569 if (qt_id) 574 if (qt_id)
570 put_ebml_string(pb, MATROSKA_ID_CODECID, "V_QUICKTIME"); 575 put_ebml_string(pb, MATROSKA_ID_CODECID, "V_QUICKTIME");
571 else if (!native_id) 576 else if (!native_id) {
572 // if there is no mkv-specific codec ID, use VFW mode 577 // if there is no mkv-specific codec ID, use VFW mode
573 put_ebml_string(pb, MATROSKA_ID_CODECID, "V_MS/VFW/FOURCC"); 578 put_ebml_string(pb, MATROSKA_ID_CODECID, "V_MS/VFW/FOURCC");
579 mkv->tracks[i].write_dts = 1;
580 }
574 581
575 subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKVIDEO, 0); 582 subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKVIDEO, 0);
576 // XXX: interlace flag? 583 // XXX: interlace flag?
577 put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , codec->width); 584 put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , codec->width);
578 put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, codec->height); 585 put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, codec->height);
672 AVMetadataTag *tag; 679 AVMetadataTag *tag;
673 int ret; 680 int ret;
674 681
675 mkv->md5_ctx = av_mallocz(av_md5_size); 682 mkv->md5_ctx = av_mallocz(av_md5_size);
676 av_md5_init(mkv->md5_ctx); 683 av_md5_init(mkv->md5_ctx);
684 mkv->tracks = av_mallocz(s->nb_streams * sizeof(*mkv->tracks));
677 685
678 ebml_header = start_ebml_master(pb, EBML_ID_HEADER, 0); 686 ebml_header = start_ebml_master(pb, EBML_ID_HEADER, 0);
679 put_ebml_uint (pb, EBML_ID_EBMLVERSION , 1); 687 put_ebml_uint (pb, EBML_ID_EBMLVERSION , 1);
680 put_ebml_uint (pb, EBML_ID_EBMLREADVERSION , 1); 688 put_ebml_uint (pb, EBML_ID_EBMLREADVERSION , 1);
681 put_ebml_uint (pb, EBML_ID_EBMLMAXIDLENGTH , 4); 689 put_ebml_uint (pb, EBML_ID_EBMLMAXIDLENGTH , 4);
811 { 819 {
812 MatroskaMuxContext *mkv = s->priv_data; 820 MatroskaMuxContext *mkv = s->priv_data;
813 AVCodecContext *codec = s->streams[pkt->stream_index]->codec; 821 AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
814 uint8_t *data = NULL; 822 uint8_t *data = NULL;
815 int size = pkt->size; 823 int size = pkt->size;
824 int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts;
816 825
817 av_log(s, AV_LOG_DEBUG, "Writing block at offset %" PRIu64 ", size %d, " 826 av_log(s, AV_LOG_DEBUG, "Writing block at offset %" PRIu64 ", size %d, "
818 "pts %" PRId64 ", dts %" PRId64 ", duration %d, flags %d\n", 827 "pts %" PRId64 ", dts %" PRId64 ", duration %d, flags %d\n",
819 url_ftell(pb), pkt->size, pkt->pts, pkt->dts, pkt->duration, flags); 828 url_ftell(pb), pkt->size, pkt->pts, pkt->dts, pkt->duration, flags);
820 if (codec->codec_id == CODEC_ID_H264 && codec->extradata_size > 0 && 829 if (codec->codec_id == CODEC_ID_H264 && codec->extradata_size > 0 &&
823 else 832 else
824 data = pkt->data; 833 data = pkt->data;
825 put_ebml_id(pb, blockid); 834 put_ebml_id(pb, blockid);
826 put_ebml_num(pb, size+4, 0); 835 put_ebml_num(pb, size+4, 0);
827 put_byte(pb, 0x80 | (pkt->stream_index + 1)); // this assumes stream_index is less than 126 836 put_byte(pb, 0x80 | (pkt->stream_index + 1)); // this assumes stream_index is less than 126
828 put_be16(pb, pkt->pts - mkv->cluster_pts); 837 put_be16(pb, ts - mkv->cluster_pts);
829 put_byte(pb, flags); 838 put_byte(pb, flags);
830 put_buffer(pb, data, size); 839 put_buffer(pb, data, size);
831 if (data != pkt->data) 840 if (data != pkt->data)
832 av_free(data); 841 av_free(data);
833 } 842 }
853 ByteIOContext *pb = s->pb; 862 ByteIOContext *pb = s->pb;
854 AVCodecContext *codec = s->streams[pkt->stream_index]->codec; 863 AVCodecContext *codec = s->streams[pkt->stream_index]->codec;
855 int keyframe = !!(pkt->flags & PKT_FLAG_KEY); 864 int keyframe = !!(pkt->flags & PKT_FLAG_KEY);
856 int duration = pkt->duration; 865 int duration = pkt->duration;
857 int ret; 866 int ret;
867 int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts;
858 868
859 if (url_is_streamed(s->pb)) { 869 if (url_is_streamed(s->pb)) {
860 if (!mkv->dyn_bc) 870 if (!mkv->dyn_bc)
861 url_open_dyn_buf(&mkv->dyn_bc); 871 url_open_dyn_buf(&mkv->dyn_bc);
862 pb = mkv->dyn_bc; 872 pb = mkv->dyn_bc;
866 ret = mkv_add_seekhead_entry(mkv->cluster_seekhead, MATROSKA_ID_CLUSTER, url_ftell(pb)); 876 ret = mkv_add_seekhead_entry(mkv->cluster_seekhead, MATROSKA_ID_CLUSTER, url_ftell(pb));
867 if (ret < 0) return ret; 877 if (ret < 0) return ret;
868 878
869 mkv->cluster_pos = url_ftell(s->pb); 879 mkv->cluster_pos = url_ftell(s->pb);
870 mkv->cluster = start_ebml_master(pb, MATROSKA_ID_CLUSTER, 0); 880 mkv->cluster = start_ebml_master(pb, MATROSKA_ID_CLUSTER, 0);
871 put_ebml_uint(pb, MATROSKA_ID_CLUSTERTIMECODE, pkt->pts); 881 put_ebml_uint(pb, MATROSKA_ID_CLUSTERTIMECODE, ts);
872 mkv->cluster_pts = pkt->pts; 882 mkv->cluster_pts = ts;
873 av_md5_update(mkv->md5_ctx, pkt->data, FFMIN(200, pkt->size)); 883 av_md5_update(mkv->md5_ctx, pkt->data, FFMIN(200, pkt->size));
874 } 884 }
875 885
876 if (codec->codec_type != CODEC_TYPE_SUBTITLE) { 886 if (codec->codec_type != CODEC_TYPE_SUBTITLE) {
877 mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe << 7); 887 mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe << 7);
884 put_ebml_uint(pb, MATROSKA_ID_BLOCKDURATION, duration); 894 put_ebml_uint(pb, MATROSKA_ID_BLOCKDURATION, duration);
885 end_ebml_master(pb, blockgroup); 895 end_ebml_master(pb, blockgroup);
886 } 896 }
887 897
888 if (codec->codec_type == CODEC_TYPE_VIDEO && keyframe) { 898 if (codec->codec_type == CODEC_TYPE_VIDEO && keyframe) {
889 ret = mkv_add_cuepoint(mkv->cues, pkt, mkv->cluster_pos); 899 ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, ts, mkv->cluster_pos);
890 if (ret < 0) return ret; 900 if (ret < 0) return ret;
891 } 901 }
892 902
893 // start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming 903 // start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming
894 if (url_is_streamed(s->pb) && (url_ftell(pb) > 32*1024 || pkt->pts > mkv->cluster_pts + 1000) 904 if (url_is_streamed(s->pb) && (url_ftell(pb) > 32*1024 || ts > mkv->cluster_pts + 1000)
895 || url_ftell(pb) > mkv->cluster_pos + 5*1024*1024 || pkt->pts > mkv->cluster_pts + 5000) { 905 || url_ftell(pb) > mkv->cluster_pos + 5*1024*1024 || ts > mkv->cluster_pts + 5000) {
896 av_log(s, AV_LOG_DEBUG, "Starting new cluster at offset %" PRIu64 906 av_log(s, AV_LOG_DEBUG, "Starting new cluster at offset %" PRIu64
897 " bytes, pts %" PRIu64 "\n", url_ftell(pb), pkt->pts); 907 " bytes, pts %" PRIu64 "\n", url_ftell(pb), ts);
898 end_ebml_master(pb, mkv->cluster); 908 end_ebml_master(pb, mkv->cluster);
899 mkv->cluster_pos = 0; 909 mkv->cluster_pos = 0;
900 if (mkv->dyn_bc) 910 if (mkv->dyn_bc)
901 mkv_flush_dynbuf(s); 911 mkv_flush_dynbuf(s);
902 } 912 }
903 913
904 mkv->duration = FFMAX(mkv->duration, pkt->pts + duration); 914 mkv->duration = FFMAX(mkv->duration, ts + duration);
905 return 0; 915 return 0;
906 } 916 }
907 917
908 static int mkv_write_trailer(AVFormatContext *s) 918 static int mkv_write_trailer(AVFormatContext *s)
909 { 919 {
947 url_fseek(pb, currentpos, SEEK_SET); 957 url_fseek(pb, currentpos, SEEK_SET);
948 } 958 }
949 959
950 end_ebml_master(pb, mkv->segment); 960 end_ebml_master(pb, mkv->segment);
951 av_free(mkv->md5_ctx); 961 av_free(mkv->md5_ctx);
962 av_free(mkv->tracks);
952 put_flush_packet(pb); 963 put_flush_packet(pb);
953 return 0; 964 return 0;
954 } 965 }
955 966
956 AVOutputFormat matroska_muxer = { 967 AVOutputFormat matroska_muxer = {