You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

327 lines
10KB

  1. /*
  2. * Sierra VMD Format Demuxer
  3. * Copyright (c) 2004 The ffmpeg Project
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2 of the License, or (at your option) any later version.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public
  16. * License along with this library; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. */
  19. /**
  20. * @file sierravmd.c
  21. * Sierra VMD file demuxer
  22. * by Vladimir "VAG" Gneushev (vagsoft at mail.ru)
  23. * for more information on the Sierra VMD file format, visit:
  24. * http://www.pcisys.net/~melanson/codecs/
  25. */
  26. #include "avformat.h"
  27. #define VMD_HEADER_SIZE 0x0330
  28. #define BYTES_PER_FRAME_RECORD 16
  29. typedef struct {
  30. int stream_index;
  31. offset_t frame_offset;
  32. unsigned int frame_size;
  33. int64_t pts;
  34. int keyframe;
  35. unsigned char frame_record[BYTES_PER_FRAME_RECORD];
  36. } vmd_frame_t;
  37. typedef struct VmdDemuxContext {
  38. int video_stream_index;
  39. int audio_stream_index;
  40. unsigned int audio_type;
  41. unsigned int audio_samplerate;
  42. unsigned int audio_bits;
  43. unsigned int audio_channels;
  44. unsigned int frame_count;
  45. vmd_frame_t *frame_table;
  46. unsigned int current_frame;
  47. int sample_rate;
  48. int64_t audio_sample_counter;
  49. int audio_frame_divisor;
  50. int audio_block_align;
  51. unsigned char vmd_header[VMD_HEADER_SIZE];
  52. } VmdDemuxContext;
  53. static int vmd_probe(AVProbeData *p)
  54. {
  55. if (p->buf_size < 2)
  56. return 0;
  57. /* check if the first 2 bytes of the file contain the appropriate size
  58. * of a VMD header chunk */
  59. if (LE_16(&p->buf[0]) != VMD_HEADER_SIZE - 2)
  60. return 0;
  61. /* only return half certainty since this check is a bit sketchy */
  62. return AVPROBE_SCORE_MAX / 2;
  63. }
  64. /* This is a support function to determine the duration, in sample
  65. * frames, of a particular audio chunk, taking into account silent
  66. * encodings. */
  67. static int vmd_calculate_audio_duration(unsigned char *audio_chunk,
  68. int audio_chunk_size, int block_align)
  69. {
  70. unsigned char *p = audio_chunk + 16;
  71. unsigned char *p_end = audio_chunk + audio_chunk_size;
  72. int total_samples = 0;
  73. unsigned int sound_flags;
  74. if (audio_chunk_size < 16)
  75. return 0;
  76. sound_flags = LE_32(p);
  77. p += 4;
  78. while (p < p_end) {
  79. total_samples += block_align;
  80. if ((sound_flags & 0x01) == 0)
  81. p += block_align;
  82. sound_flags >>= 1;
  83. }
  84. return total_samples;
  85. }
  86. static int vmd_read_header(AVFormatContext *s,
  87. AVFormatParameters *ap)
  88. {
  89. VmdDemuxContext *vmd = (VmdDemuxContext *)s->priv_data;
  90. ByteIOContext *pb = &s->pb;
  91. AVStream *st;
  92. unsigned int toc_offset;
  93. unsigned char *raw_frame_table;
  94. int raw_frame_table_size;
  95. unsigned char *current_frame_record;
  96. offset_t current_offset;
  97. int i;
  98. unsigned int total_frames;
  99. int64_t video_pts_inc;
  100. int64_t current_video_pts = 0;
  101. /* fetch the main header, including the 2 header length bytes */
  102. url_fseek(pb, 0, SEEK_SET);
  103. if (get_buffer(pb, vmd->vmd_header, VMD_HEADER_SIZE) != VMD_HEADER_SIZE)
  104. return AVERROR_IO;
  105. vmd->audio_sample_counter = 0;
  106. vmd->audio_frame_divisor = 1;
  107. vmd->audio_block_align = 1;
  108. /* start up the decoders */
  109. st = av_new_stream(s, 0);
  110. if (!st)
  111. return AVERROR_NOMEM;
  112. av_set_pts_info(st, 33, 1, 90000);
  113. vmd->video_stream_index = st->index;
  114. st->codec.codec_type = CODEC_TYPE_VIDEO;
  115. st->codec.codec_id = CODEC_ID_VMDVIDEO;
  116. st->codec.codec_tag = 0; /* no fourcc */
  117. st->codec.width = LE_16(&vmd->vmd_header[12]);
  118. st->codec.height = LE_16(&vmd->vmd_header[14]);
  119. st->codec.extradata_size = VMD_HEADER_SIZE;
  120. st->codec.extradata = av_malloc(VMD_HEADER_SIZE);
  121. memcpy(st->codec.extradata, vmd->vmd_header, VMD_HEADER_SIZE);
  122. /* if sample rate is 0, assume no audio */
  123. vmd->sample_rate = LE_16(&vmd->vmd_header[804]);
  124. if (vmd->sample_rate) {
  125. st = av_new_stream(s, 0);
  126. if (!st)
  127. return AVERROR_NOMEM;
  128. av_set_pts_info(st, 33, 1, 90000);
  129. vmd->audio_stream_index = st->index;
  130. st->codec.codec_type = CODEC_TYPE_AUDIO;
  131. st->codec.codec_id = CODEC_ID_VMDAUDIO;
  132. st->codec.codec_tag = 0; /* no codec tag */
  133. st->codec.channels = (vmd->vmd_header[811] & 0x80) ? 2 : 1;
  134. st->codec.sample_rate = vmd->sample_rate;
  135. st->codec.block_align = vmd->audio_block_align =
  136. LE_16(&vmd->vmd_header[806]);
  137. if (st->codec.block_align & 0x8000) {
  138. st->codec.bits_per_sample = 16;
  139. st->codec.block_align = -(st->codec.block_align - 0x10000);
  140. } else
  141. st->codec.bits_per_sample = 16;
  142. // st->codec.bits_per_sample = 8;
  143. st->codec.bit_rate = st->codec.sample_rate *
  144. st->codec.bits_per_sample * st->codec.channels;
  145. /* for calculating pts */
  146. vmd->audio_frame_divisor = st->codec.bits_per_sample / 8 /
  147. st->codec.channels;
  148. video_pts_inc = 90000;
  149. video_pts_inc *= st->codec.block_align;
  150. video_pts_inc /= st->codec.sample_rate;
  151. } else {
  152. /* if no audio, assume 10 frames/second */
  153. video_pts_inc = 90000 / 10;
  154. }
  155. /* skip over the offset table and load the table of contents; don't
  156. * care about the offset table since demuxer will calculate those
  157. * independently */
  158. toc_offset = LE_32(&vmd->vmd_header[812]);
  159. vmd->frame_count = LE_16(&vmd->vmd_header[6]);
  160. url_fseek(pb, toc_offset + vmd->frame_count * 6, SEEK_SET);
  161. /* each on-disk VMD frame has an audio part and a video part; demuxer
  162. * accounts them separately */
  163. if(vmd->sample_rate)
  164. vmd->frame_count *= 2;
  165. raw_frame_table = NULL;
  166. vmd->frame_table = NULL;
  167. raw_frame_table_size = vmd->frame_count * BYTES_PER_FRAME_RECORD;
  168. raw_frame_table = av_malloc(raw_frame_table_size);
  169. vmd->frame_table = av_malloc(vmd->frame_count * sizeof(vmd_frame_t));
  170. if (!raw_frame_table || !vmd->frame_table) {
  171. av_free(raw_frame_table);
  172. av_free(vmd->frame_table);
  173. return AVERROR_NOMEM;
  174. }
  175. if (get_buffer(pb, raw_frame_table, raw_frame_table_size) !=
  176. raw_frame_table_size) {
  177. av_free(raw_frame_table);
  178. av_free(vmd->frame_table);
  179. return AVERROR_IO;
  180. }
  181. current_offset = LE_32(&vmd->vmd_header[20]);
  182. current_frame_record = raw_frame_table;
  183. total_frames = vmd->frame_count;
  184. i = 0;
  185. while (total_frames--) {
  186. /* if the frame size is 0, do not count the frame and bring the
  187. * total frame count down */
  188. // note, we limit the size to 1Gb to ensure that we dont end up overflowing the size integer used to allocate the memory
  189. vmd->frame_table[i].frame_size = LE_32(&current_frame_record[2]) & 0x3FFFFFFF;
  190. /* this logic is present so that 0-length audio chunks are not
  191. * accounted */
  192. if (!vmd->frame_table[i].frame_size) {
  193. vmd->frame_count--; /* one less frame to count */
  194. current_frame_record += BYTES_PER_FRAME_RECORD;
  195. continue;
  196. }
  197. if (current_frame_record[0] == 0x02)
  198. vmd->frame_table[i].stream_index = vmd->video_stream_index;
  199. else
  200. vmd->frame_table[i].stream_index = vmd->audio_stream_index;
  201. vmd->frame_table[i].frame_offset = current_offset;
  202. current_offset += vmd->frame_table[i].frame_size;
  203. memcpy(vmd->frame_table[i].frame_record, current_frame_record,
  204. BYTES_PER_FRAME_RECORD);
  205. /* figure out the pts for this frame */
  206. if (current_frame_record[0] == 0x02) {
  207. vmd->frame_table[i].pts = current_video_pts;
  208. current_video_pts += video_pts_inc;
  209. } else if (current_frame_record[0] == 0x01) {
  210. /* figure out the pts during the dispatch phase */
  211. vmd->frame_table[i].pts = 0;
  212. }
  213. current_frame_record += BYTES_PER_FRAME_RECORD;
  214. i++;
  215. }
  216. av_free(raw_frame_table);
  217. vmd->current_frame = 0;
  218. return 0;
  219. }
  220. static int vmd_read_packet(AVFormatContext *s,
  221. AVPacket *pkt)
  222. {
  223. VmdDemuxContext *vmd = (VmdDemuxContext *)s->priv_data;
  224. ByteIOContext *pb = &s->pb;
  225. int ret = 0;
  226. vmd_frame_t *frame;
  227. if (vmd->current_frame >= vmd->frame_count)
  228. return AVERROR_IO;
  229. frame = &vmd->frame_table[vmd->current_frame];
  230. /* position the stream (will probably be there already) */
  231. url_fseek(pb, frame->frame_offset, SEEK_SET);
  232. if (av_new_packet(pkt, frame->frame_size + BYTES_PER_FRAME_RECORD))
  233. return AVERROR_NOMEM;
  234. pkt->pos= url_ftell(pb);
  235. memcpy(pkt->data, frame->frame_record, BYTES_PER_FRAME_RECORD);
  236. ret = get_buffer(pb, pkt->data + BYTES_PER_FRAME_RECORD,
  237. frame->frame_size);
  238. if (ret != frame->frame_size) {
  239. av_free_packet(pkt);
  240. ret = AVERROR_IO;
  241. }
  242. pkt->stream_index = frame->stream_index;
  243. if (frame->frame_record[0] == 0x02)
  244. pkt->pts = frame->pts;
  245. else {
  246. pkt->pts = vmd->audio_sample_counter;
  247. pkt->pts *= 90000;
  248. pkt->pts /= vmd->sample_rate;
  249. // pkt->pts /= vmd->audio_frame_divisor;
  250. vmd->audio_sample_counter += vmd_calculate_audio_duration(
  251. pkt->data, pkt->size, vmd->audio_block_align);
  252. }
  253. av_log(NULL, AV_LOG_INFO, " dispatching %s frame with %d bytes and pts %lld (%0.1f sec)\n",
  254. (frame->frame_record[0] == 0x02) ? "video" : "audio",
  255. frame->frame_size + BYTES_PER_FRAME_RECORD,
  256. pkt->pts, (float)(pkt->pts / 90000.0));
  257. vmd->current_frame++;
  258. return ret;
  259. }
  260. static int vmd_read_close(AVFormatContext *s)
  261. {
  262. VmdDemuxContext *vmd = (VmdDemuxContext *)s->priv_data;
  263. av_free(vmd->frame_table);
  264. return 0;
  265. }
  266. static AVInputFormat vmd_iformat = {
  267. "vmd",
  268. "Sierra VMD format",
  269. sizeof(VmdDemuxContext),
  270. vmd_probe,
  271. vmd_read_header,
  272. vmd_read_packet,
  273. vmd_read_close,
  274. };
  275. int vmd_init(void)
  276. {
  277. av_register_input_format(&vmd_iformat);
  278. return 0;
  279. }