comparison mxfenc.c @ 4312:385b2fdccbbb libavformat

correctly pack and interleave pcm samples in mxf
author bcoudurier
date Sat, 31 Jan 2009 06:18:25 +0000
parents 2402eb8c37ff
children bdb984bfa3ed
comparison
equal deleted inserted replaced
4311:03065a598506 4312:385b2fdccbbb
29 * SMPTE RP224: Registry of SMPTE Universal Labels 29 * SMPTE RP224: Registry of SMPTE Universal Labels
30 */ 30 */
31 31
32 //#define DEBUG 32 //#define DEBUG
33 33
34 #include "libavutil/fifo.h"
34 #include "mxf.h" 35 #include "mxf.h"
36
37 static const int NTSC_samples_per_frame[] = { 1602, 1601, 1602, 1601, 1602, 0 };
38 static const int PAL_samples_per_frame[] = { 1920, 0 };
39
40 typedef struct {
41 AVFifoBuffer fifo;
42 unsigned fifo_size; ///< current fifo size allocated
43 uint64_t dts; ///< current dts
44 int sample_size; ///< size of one sample all channels included
45 const int *samples_per_frame; ///< must be 0 terminated
46 const int *samples; ///< current samples per frame, pointer to samples_per_frame
47 } AudioInterleaveContext;
35 48
36 typedef struct { 49 typedef struct {
37 int local_tag; 50 int local_tag;
38 UID uid; 51 UID uid;
39 } MXFLocalTagPair; 52 } MXFLocalTagPair;
40 53
41 typedef struct { 54 typedef struct {
55 AudioInterleaveContext aic;
42 UID track_essence_element_key; 56 UID track_essence_element_key;
43 int index; //<<< index in mxf_essence_container_uls table 57 int index; //<<< index in mxf_essence_container_uls table
44 const UID *codec_ul; 58 const UID *codec_ul;
45 int64_t duration; 59 int64_t duration;
60 int order; ///< interleaving order if dts are equal
46 } MXFStreamContext; 61 } MXFStreamContext;
47 62
48 typedef struct { 63 typedef struct {
49 UID container_ul; 64 UID container_ul;
50 UID element_ul; 65 UID element_ul;
73 88
74 typedef struct MXFContext { 89 typedef struct MXFContext {
75 int64_t footer_partition_offset; 90 int64_t footer_partition_offset;
76 int essence_container_count; 91 int essence_container_count;
77 uint8_t essence_containers_indices[FF_ARRAY_ELEMS(mxf_essence_container_uls)]; 92 uint8_t essence_containers_indices[FF_ARRAY_ELEMS(mxf_essence_container_uls)];
93 AVRational time_base;
78 } MXFContext; 94 } MXFContext;
79 95
80 static const uint8_t uuid_base[] = { 0xAD,0xAB,0x44,0x24,0x2f,0x25,0x4d,0xc7,0x92,0xff,0x29,0xbd }; 96 static const uint8_t uuid_base[] = { 0xAD,0xAB,0x44,0x24,0x2f,0x25,0x4d,0xc7,0x92,0xff,0x29,0xbd };
81 static const uint8_t umid_base[] = { 0x06,0x0A,0x2B,0x34,0x01,0x01,0x01,0x05,0x01,0x01,0x0D,0x00,0x13,0x00,0x00,0x00 }; 97 static const uint8_t umid_base[] = { 0x06,0x0A,0x2B,0x34,0x01,0x01,0x01,0x05,0x01,0x01,0x0D,0x00,0x13,0x00,0x00,0x00 };
82 98
779 &mxf_mpeg2_codec_uls[6]; 795 &mxf_mpeg2_codec_uls[6];
780 } 796 }
781 return NULL; 797 return NULL;
782 } 798 }
783 799
800 static int ff_audio_interleave_init(AVFormatContext *s, const int *samples_per_frame)
801 {
802 int i;
803
804 if (!samples_per_frame)
805 samples_per_frame = PAL_samples_per_frame;
806
807 for (i = 0; i < s->nb_streams; i++) {
808 AVStream *st = s->streams[i];
809 AudioInterleaveContext *aic = st->priv_data;
810
811 if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
812 aic->sample_size = (st->codec->channels *
813 av_get_bits_per_sample(st->codec->codec_id)) / 8;
814 if (!aic->sample_size) {
815 av_log(s, AV_LOG_ERROR, "could not compute sample size\n");
816 return -1;
817 }
818 aic->samples_per_frame = samples_per_frame;
819 aic->samples = aic->samples_per_frame;
820
821 av_fifo_init(&aic->fifo, 100 * *aic->samples);
822 }
823 }
824
825 return 0;
826 }
827
784 static int mxf_write_header(AVFormatContext *s) 828 static int mxf_write_header(AVFormatContext *s)
785 { 829 {
786 MXFContext *mxf = s->priv_data; 830 MXFContext *mxf = s->priv_data;
787 int i; 831 int i;
788 uint8_t present[FF_ARRAY_ELEMS(mxf_essence_container_uls)] = {0}; 832 uint8_t present[FF_ARRAY_ELEMS(mxf_essence_container_uls)] = {0};
833 const int *samples_per_frame = NULL;
789 834
790 for (i = 0; i < s->nb_streams; i++) { 835 for (i = 0; i < s->nb_streams; i++) {
791 AVStream *st = s->streams[i]; 836 AVStream *st = s->streams[i];
792 MXFStreamContext *sc = av_mallocz(sizeof(*sc)); 837 MXFStreamContext *sc = av_mallocz(sizeof(*sc));
793 if (!sc) 838 if (!sc)
794 return AVERROR(ENOMEM); 839 return AVERROR(ENOMEM);
795 st->priv_data = sc; 840 st->priv_data = sc;
796 // set pts information 841
797 if (st->codec->codec_type == CODEC_TYPE_VIDEO) 842 if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
798 av_set_pts_info(st, 64, 1, st->codec->time_base.den); 843 if (!av_cmp_q(st->codec->time_base, (AVRational){ 1, 25 })) {
799 else if (st->codec->codec_type == CODEC_TYPE_AUDIO) 844 samples_per_frame = PAL_samples_per_frame;
800 av_set_pts_info(st, 64, 1, st->codec->sample_rate); 845 mxf->time_base = (AVRational){ 1, 25 };
846 } else if (!av_cmp_q(st->codec->time_base, (AVRational){ 1001, 30000 })) {
847 samples_per_frame = NTSC_samples_per_frame;
848 mxf->time_base = (AVRational){ 1001, 30000 };
849 } else {
850 av_log(s, AV_LOG_ERROR, "unsupported video frame rate\n");
851 return -1;
852 }
853 } else if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
854 if (st->codec->sample_rate != 48000) {
855 av_log(s, AV_LOG_ERROR, "only 48khz is implemented\n");
856 return -1;
857 }
858 }
801 sc->duration = -1; 859 sc->duration = -1;
802 860
803 sc->index = mxf_get_essence_container_ul_index(st->codec->codec_id); 861 sc->index = mxf_get_essence_container_ul_index(st->codec->codec_id);
804 if (sc->index == -1) { 862 if (sc->index == -1) {
805 av_log(s, AV_LOG_ERROR, "track %d: could not find essence container ul, " 863 av_log(s, AV_LOG_ERROR, "track %d: could not find essence container ul, "
830 memcpy(sc->track_essence_element_key, mxf_essence_container_uls[sc->index].element_ul, 15); 888 memcpy(sc->track_essence_element_key, mxf_essence_container_uls[sc->index].element_ul, 15);
831 sc->track_essence_element_key[15] = present[sc->index]; 889 sc->track_essence_element_key[15] = present[sc->index];
832 PRINT_KEY(s, "track essence element key", sc->track_essence_element_key); 890 PRINT_KEY(s, "track essence element key", sc->track_essence_element_key);
833 } 891 }
834 892
893 for (i = 0; i < s->nb_streams; i++) {
894 MXFStreamContext *sc = s->streams[i]->priv_data;
895 av_set_pts_info(s->streams[i], 64, mxf->time_base.num, mxf->time_base.den);
896 // update element count
897 sc->track_essence_element_key[13] = present[sc->index];
898 sc->order = AV_RB32(sc->track_essence_element_key+12);
899 }
900
901 if (ff_audio_interleave_init(s, samples_per_frame) < 0)
902 return -1;
903
835 mxf_write_partition(s, 1, header_open_partition_key, 1); 904 mxf_write_partition(s, 1, header_open_partition_key, 1);
836 905
837 return 0; 906 return 0;
838 } 907 }
839 908
864 url_fseek(pb, 0, SEEK_SET); 933 url_fseek(pb, 0, SEEK_SET);
865 mxf_write_partition(s, 1, header_closed_partition_key, 1); 934 mxf_write_partition(s, 1, header_closed_partition_key, 1);
866 } 935 }
867 mxf_free(s); 936 mxf_free(s);
868 return 0; 937 return 0;
938 }
939
940 static int mxf_interleave_new_audio_packet(AVFormatContext *s, AVPacket *pkt,
941 int stream_index, int flush)
942 {
943 AVStream *st = s->streams[stream_index];
944 AudioInterleaveContext *aic = st->priv_data;
945
946 int size = FFMIN(av_fifo_size(&aic->fifo), *aic->samples * aic->sample_size);
947 if (!size || (!flush && size == av_fifo_size(&aic->fifo)))
948 return 0;
949
950 av_new_packet(pkt, size);
951 av_fifo_read(&aic->fifo, pkt->data, size);
952
953 pkt->dts = pkt->pts = aic->dts;
954 pkt->duration = av_rescale_q(*aic->samples,
955 (AVRational){ 1, st->codec->sample_rate },
956 st->time_base);
957 pkt->stream_index = stream_index;
958 aic->dts += pkt->duration;
959
960 aic->samples++;
961 if (!*aic->samples)
962 aic->samples = aic->samples_per_frame;
963
964 return size;
965 }
966
967 static int mxf_interleave_get_packet(AVFormatContext *s, AVPacket *out, int flush)
968 {
969 AVPacketList *pktl;
970 int stream_count = 0;
971 int streams[MAX_STREAMS];
972
973 memset(streams, 0, sizeof(streams));
974 pktl = s->packet_buffer;
975 while (pktl) {
976 //av_log(s, AV_LOG_DEBUG, "show st:%d dts:%lld\n", pktl->pkt.stream_index, pktl->pkt.dts);
977 if (!streams[pktl->pkt.stream_index])
978 stream_count++;
979 streams[pktl->pkt.stream_index]++;
980 pktl = pktl->next;
981 }
982
983 if (stream_count && (s->nb_streams == stream_count || flush)) {
984 pktl = s->packet_buffer;
985 *out = pktl->pkt;
986 //av_log(s, AV_LOG_DEBUG, "out st:%d dts:%lld\n", (*out).stream_index, (*out).dts);
987 s->packet_buffer = pktl->next;
988 av_freep(&pktl);
989
990 if (flush && stream_count < s->nb_streams) {
991 // purge packet queue
992 pktl = s->packet_buffer;
993 while (pktl) {
994 AVPacketList *next = pktl->next;
995 av_free_packet(&pktl->pkt);
996 av_freep(&pktl);
997 pktl = next;
998 }
999 s->packet_buffer = NULL;
1000 }
1001
1002 return 1;
1003 } else {
1004 av_init_packet(out);
1005 return 0;
1006 }
1007 }
1008
1009 static int mxf_compare_timestamps(AVFormatContext *s, AVPacket *next, AVPacket *pkt)
1010 {
1011 AVStream *st = s->streams[pkt ->stream_index];
1012 AVStream *st2 = s->streams[next->stream_index];
1013 MXFStreamContext *sc = st ->priv_data;
1014 MXFStreamContext *sc2 = st2->priv_data;
1015
1016 int64_t left = st2->time_base.num * (int64_t)st ->time_base.den;
1017 int64_t right = st ->time_base.num * (int64_t)st2->time_base.den;
1018
1019 return next->dts * left > pkt->dts * right || // FIXME this can overflow
1020 (next->dts * left == pkt->dts * right && sc->order < sc2->order);
1021 }
1022
1023 static int mxf_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush)
1024 {
1025 int i;
1026
1027 if (pkt) {
1028 AVStream *st = s->streams[pkt->stream_index];
1029 AudioInterleaveContext *aic = st->priv_data;
1030 if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
1031 av_fifo_generic_write(&aic->fifo, pkt->data, pkt->size, NULL);
1032 } else {
1033 // rewrite pts and dts to be decoded time line position
1034 pkt->pts = pkt->dts = aic->dts;
1035 aic->dts += pkt->duration;
1036 ff_interleave_add_packet(s, pkt, mxf_compare_timestamps);
1037 }
1038 }
1039
1040 for (i = 0; i < s->nb_streams; i++) {
1041 AVStream *st = s->streams[i];
1042 if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
1043 AVPacket new_pkt;
1044 while (mxf_interleave_new_audio_packet(s, &new_pkt, i, flush))
1045 ff_interleave_add_packet(s, &new_pkt, mxf_compare_timestamps);
1046 }
1047 }
1048
1049 return mxf_interleave_get_packet(s, out, flush);
869 } 1050 }
870 1051
871 AVOutputFormat mxf_muxer = { 1052 AVOutputFormat mxf_muxer = {
872 "mxf", 1053 "mxf",
873 NULL_IF_CONFIG_SMALL("Material eXchange Format"), 1054 NULL_IF_CONFIG_SMALL("Material eXchange Format"),
877 CODEC_ID_PCM_S16LE, 1058 CODEC_ID_PCM_S16LE,
878 CODEC_ID_MPEG2VIDEO, 1059 CODEC_ID_MPEG2VIDEO,
879 mxf_write_header, 1060 mxf_write_header,
880 mxf_write_packet, 1061 mxf_write_packet,
881 mxf_write_footer, 1062 mxf_write_footer,
1063 0,
1064 NULL,
1065 mxf_interleave,
882 }; 1066 };
883 1067
884 1068