00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "libavutil/intreadwrite.h"
00023 #include "libavutil/dict.h"
00024 #include "avformat.h"
00025
00026 #define AUPR_HDR 0x415550522D484452
00027 #define AUPRINFO 0x41555052494E464F
00028 #define BITSHVTB 0x4249545348565442
00029 #define BLACKOUT 0x424C41434B4F5554
00030 #define BRANCHPT 0x4252414E43485054
00031 #define BUILDVER 0x4255494C44564552
00032 #define CORESSMD 0x434F524553534D44
00033 #define DTSHDHDR 0x4454534844484452
00034 #define EXTSS_MD 0x45585453535f4d44
00035 #define FILEINFO 0x46494C45494E464F
00036 #define NAVI_TBL 0x4E4156492D54424C
00037 #define STRMDATA 0x5354524D44415441
00038 #define TIMECODE 0x54494D45434F4445
00039
00040 typedef struct DTSHDDemuxContext {
00041 uint64_t data_end;
00042 } DTSHDDemuxContext;
00043
00044 static int dtshd_probe(AVProbeData *p)
00045 {
00046 if (AV_RB64(p->buf) == DTSHDHDR)
00047 return AVPROBE_SCORE_MAX;
00048 return 0;
00049 }
00050
00051 static int dtshd_read_header(AVFormatContext *s)
00052 {
00053 DTSHDDemuxContext *dtshd = s->priv_data;
00054 AVIOContext *pb = s->pb;
00055 uint64_t chunk_type, chunk_size;
00056 AVStream *st;
00057 int ret;
00058 char *value;
00059
00060 st = avformat_new_stream(s, NULL);
00061 if (!st)
00062 return AVERROR(ENOMEM);
00063 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00064 st->codec->codec_id = AV_CODEC_ID_DTS;
00065 st->need_parsing = AVSTREAM_PARSE_FULL_RAW;
00066
00067 while (!url_feof(pb)) {
00068 chunk_type = avio_rb64(pb);
00069 chunk_size = avio_rb64(pb);
00070
00071 if (chunk_size < 4) {
00072 av_log(s, AV_LOG_ERROR, "chunk size too small\n");
00073 return AVERROR_INVALIDDATA;
00074 }
00075 if (chunk_size > ((uint64_t)1 << 61)) {
00076 av_log(s, AV_LOG_ERROR, "chunk size too big\n");
00077 return AVERROR_INVALIDDATA;
00078 }
00079
00080 switch (chunk_type) {
00081 case STRMDATA:
00082 dtshd->data_end = chunk_size + avio_tell(pb);
00083 if (dtshd->data_end <= chunk_size)
00084 return AVERROR_INVALIDDATA;
00085 return 0;
00086 break;
00087 case FILEINFO:
00088 if (chunk_size > INT_MAX)
00089 goto skip;
00090 value = av_malloc(chunk_size);
00091 if (!value)
00092 goto skip;
00093 avio_read(pb, value, chunk_size);
00094 value[chunk_size - 1] = 0;
00095 av_dict_set(&s->metadata, "fileinfo", value,
00096 AV_DICT_DONT_STRDUP_VAL);
00097 break;
00098 default:
00099 skip:
00100 ret = avio_skip(pb, chunk_size);
00101 if (ret < 0)
00102 return ret;
00103 };
00104 }
00105
00106 return AVERROR_EOF;
00107 }
00108
00109 static int raw_read_packet(AVFormatContext *s, AVPacket *pkt)
00110 {
00111 DTSHDDemuxContext *dtshd = s->priv_data;
00112 int64_t size, left;
00113 int ret;
00114
00115 left = dtshd->data_end - avio_tell(s->pb);
00116 size = FFMIN(left, 1024);
00117 if (size <= 0)
00118 return AVERROR_EOF;
00119
00120 ret = av_get_packet(s->pb, pkt, size);
00121 if (ret < 0)
00122 return ret;
00123
00124 pkt->stream_index = 0;
00125
00126 return ret;
00127 }
00128
00129 AVInputFormat ff_dtshd_demuxer = {
00130 .name = "dtshd",
00131 .long_name = NULL_IF_CONFIG_SMALL("raw DTS-HD"),
00132 .priv_data_size = sizeof(DTSHDDemuxContext),
00133 .read_probe = dtshd_probe,
00134 .read_header = dtshd_read_header,
00135 .read_packet = raw_read_packet,
00136 .flags = AVFMT_GENERIC_INDEX,
00137 .extensions = "dtshd",
00138 .raw_codec_id = AV_CODEC_ID_DTS,
00139 };