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.

324 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. vmd->frame_count *= 2;
  164. raw_frame_table = NULL;
  165. vmd->frame_table = NULL;
  166. raw_frame_table_size = vmd->frame_count * BYTES_PER_FRAME_RECORD;
  167. raw_frame_table = av_malloc(raw_frame_table_size);
  168. vmd->frame_table = av_malloc(vmd->frame_count * sizeof(vmd_frame_t));
  169. if (!raw_frame_table || !vmd->frame_table) {
  170. av_free(raw_frame_table);
  171. av_free(vmd->frame_table);
  172. return AVERROR_NOMEM;
  173. }
  174. if (get_buffer(pb, raw_frame_table, raw_frame_table_size) !=
  175. raw_frame_table_size) {
  176. av_free(raw_frame_table);
  177. av_free(vmd->frame_table);
  178. return AVERROR_IO;
  179. }
  180. current_offset = LE_32(&vmd->vmd_header[20]);
  181. current_frame_record = raw_frame_table;
  182. total_frames = vmd->frame_count;
  183. i = 0;
  184. while (total_frames--) {
  185. /* if the frame size is 0, do not count the frame and bring the
  186. * total frame count down */
  187. vmd->frame_table[i].frame_size = LE_32(&current_frame_record[2]);
  188. /* this logic is present so that 0-length audio chunks are not
  189. * accounted */
  190. if (!vmd->frame_table[i].frame_size) {
  191. vmd->frame_count--; /* one less frame to count */
  192. current_frame_record += BYTES_PER_FRAME_RECORD;
  193. continue;
  194. }
  195. if (current_frame_record[0] == 0x02)
  196. vmd->frame_table[i].stream_index = vmd->video_stream_index;
  197. else
  198. vmd->frame_table[i].stream_index = vmd->audio_stream_index;
  199. vmd->frame_table[i].frame_offset = current_offset;
  200. current_offset += vmd->frame_table[i].frame_size;
  201. memcpy(vmd->frame_table[i].frame_record, current_frame_record,
  202. BYTES_PER_FRAME_RECORD);
  203. /* figure out the pts for this frame */
  204. if (current_frame_record[0] == 0x02) {
  205. vmd->frame_table[i].pts = current_video_pts;
  206. current_video_pts += video_pts_inc;
  207. } else if (current_frame_record[0] == 0x01) {
  208. /* figure out the pts during the dispatch phase */
  209. vmd->frame_table[i].pts = 0;
  210. }
  211. current_frame_record += BYTES_PER_FRAME_RECORD;
  212. i++;
  213. }
  214. av_free(raw_frame_table);
  215. vmd->current_frame = 0;
  216. return 0;
  217. }
  218. static int vmd_read_packet(AVFormatContext *s,
  219. AVPacket *pkt)
  220. {
  221. VmdDemuxContext *vmd = (VmdDemuxContext *)s->priv_data;
  222. ByteIOContext *pb = &s->pb;
  223. int ret = 0;
  224. vmd_frame_t *frame;
  225. if (vmd->current_frame >= vmd->frame_count)
  226. return AVERROR_IO;
  227. frame = &vmd->frame_table[vmd->current_frame];
  228. /* position the stream (will probably be there already) */
  229. url_fseek(pb, frame->frame_offset, SEEK_SET);
  230. if (av_new_packet(pkt, frame->frame_size + BYTES_PER_FRAME_RECORD))
  231. return AVERROR_NOMEM;
  232. memcpy(pkt->data, frame->frame_record, BYTES_PER_FRAME_RECORD);
  233. ret = get_buffer(pb, pkt->data + BYTES_PER_FRAME_RECORD,
  234. frame->frame_size);
  235. if (ret != frame->frame_size) {
  236. av_free_packet(pkt);
  237. ret = AVERROR_IO;
  238. }
  239. pkt->stream_index = frame->stream_index;
  240. if (frame->frame_record[0] == 0x02)
  241. pkt->pts = frame->pts;
  242. else {
  243. pkt->pts = vmd->audio_sample_counter;
  244. pkt->pts *= 90000;
  245. pkt->pts /= vmd->sample_rate;
  246. // pkt->pts /= vmd->audio_frame_divisor;
  247. vmd->audio_sample_counter += vmd_calculate_audio_duration(
  248. pkt->data, pkt->size, vmd->audio_block_align);
  249. }
  250. printf (" dispatching %s frame with %d bytes and pts %lld (%0.1f sec)\n",
  251. (frame->frame_record[0] == 0x02) ? "video" : "audio",
  252. frame->frame_size + BYTES_PER_FRAME_RECORD,
  253. pkt->pts, (float)(pkt->pts / 90000.0));
  254. vmd->current_frame++;
  255. return ret;
  256. }
  257. static int vmd_read_close(AVFormatContext *s)
  258. {
  259. VmdDemuxContext *vmd = (VmdDemuxContext *)s->priv_data;
  260. av_free(vmd->frame_table);
  261. return 0;
  262. }
  263. static AVInputFormat vmd_iformat = {
  264. "vmd",
  265. "Sierra VMD format",
  266. sizeof(VmdDemuxContext),
  267. vmd_probe,
  268. vmd_read_header,
  269. vmd_read_packet,
  270. vmd_read_close,
  271. };
  272. int vmd_init(void)
  273. {
  274. av_register_input_format(&vmd_iformat);
  275. return 0;
  276. }