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.

511 lines
15KB

  1. /*
  2. * ASF compatible encoder
  3. * Copyright (c) 2000 Gerard Lantau.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program 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
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <netinet/in.h>
  22. #include <string.h>
  23. #include "mpegenc.h"
  24. #define PACKET_SIZE 3200
  25. #define PACKET_HEADER_SIZE 12
  26. #define FRAME_HEADER_SIZE 17
  27. typedef struct {
  28. AVEncodeContext *enc;
  29. int num;
  30. int seq;
  31. } ASFStream;
  32. typedef struct {
  33. int is_streamed; /* true if streamed */
  34. int seqno;
  35. int packet_size;
  36. ASFStream streams[2];
  37. ASFStream *audio_stream, *video_stream;
  38. int nb_streams;
  39. /* non streamed additonnal info */
  40. int file_size_offset;
  41. int data_offset;
  42. /* packet filling */
  43. int packet_size_left;
  44. int packet_timestamp_start;
  45. int packet_timestamp_end;
  46. int packet_nb_frames;
  47. UINT8 packet_buf[PACKET_SIZE];
  48. PutByteContext pb;
  49. } ASFContext;
  50. typedef struct {
  51. UINT32 v1;
  52. UINT16 v2;
  53. UINT16 v3;
  54. UINT8 v4[8];
  55. } GUID;
  56. static const GUID asf_header = {
  57. 0x75B22630, 0x668E, 0x11CF, { 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C },
  58. };
  59. static const GUID file_header = {
  60. 0x8CABDCA1, 0xA947, 0x11CF, { 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 },
  61. };
  62. static const GUID stream_header = {
  63. 0xB7DC0791, 0xA9B7, 0x11CF, { 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 },
  64. };
  65. static const GUID audio_stream = {
  66. 0xF8699E40, 0x5B4D, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B },
  67. };
  68. static const GUID audio_conceal_none = {
  69. 0x49f1a440, 0x4ece, 0x11d0, { 0xa3, 0xac, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6 },
  70. };
  71. static const GUID video_stream = {
  72. 0xBC19EFC0, 0x5B4D, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B },
  73. };
  74. static const GUID video_conceal_none = {
  75. 0x20FB5700, 0x5B55, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B },
  76. };
  77. static const GUID comment_header = {
  78. 0x86D15240, 0x311D, 0x11D0, { 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 },
  79. };
  80. static const GUID data_header = {
  81. 0x75b22636, 0x668e, 0x11cf, { 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c },
  82. };
  83. static const GUID packet_guid = {
  84. 0xF656CCE1, 0x03B3, 0x11D4, { 0xBE, 0xA2, 0x00, 0xA0, 0xCC, 0x3D, 0x72, 0x74 },
  85. };
  86. /* I am not a number !!! This GUID is the one found on the PC used to
  87. generate the stream */
  88. static const GUID my_guid = {
  89. 0x12345678, 0xA947, 0x11CF, { 0x31, 0x41, 0x59, 0x26, 0x20, 0x20, 0x20, 0x20 },
  90. };
  91. static void put_guid(PutByteContext *s, const GUID *g)
  92. {
  93. int i;
  94. put_le32(s, g->v1);
  95. put_le16(s, g->v2);
  96. put_le16(s, g->v3);
  97. for(i=0;i<8;i++)
  98. put_byte(s, g->v4[i]);
  99. }
  100. #if 0
  101. static void put_str16(PutByteContext *s, const char *tag)
  102. {
  103. put_le16(s,strlen(tag));
  104. while (*tag) {
  105. put_le16(s, *tag++);
  106. }
  107. }
  108. #endif
  109. /* write an asf chunk (only used in streaming case) */
  110. static void put_chunk(AVFormatContext *s, int type, int payload_length)
  111. {
  112. ASFContext *asf = s->priv_data;
  113. PutByteContext *pb = &s->pb;
  114. int length;
  115. length = payload_length + 8;
  116. put_le16(pb, type);
  117. put_le16(pb, length);
  118. put_le32(pb, asf->seqno);
  119. put_le16(pb, 0); /* unknown bytes */
  120. put_le16(pb, length);
  121. asf->seqno++;
  122. }
  123. static int asf_write_header(AVFormatContext *s)
  124. {
  125. PutByteContext *pb = &s->pb;
  126. ASFContext *asf;
  127. int header_size, n, extra_size, extra_size2, i, wav_extra_size;
  128. AVEncodeContext *enc;
  129. long long header_offset, cur_pos;
  130. asf = malloc(sizeof(ASFContext));
  131. if (!asf)
  132. return -1;
  133. memset(asf, 0, sizeof(ASFContext));
  134. s->priv_data = asf;
  135. asf->packet_size = PACKET_SIZE;
  136. if (!s->is_streamed) {
  137. put_guid(pb, &asf_header);
  138. put_le64(pb, 0); /* header length, will be patched after */
  139. put_le32(pb, 6); /* ??? */
  140. put_byte(pb, 1); /* ??? */
  141. put_byte(pb, 2); /* ??? */
  142. } else {
  143. put_chunk(s, 0x4824, 0); /* start of stream (length will be patched later) */
  144. }
  145. /* file header */
  146. header_offset = put_pos(pb);
  147. put_guid(pb, &file_header);
  148. put_le64(pb, 24 + 80);
  149. put_guid(pb, &my_guid);
  150. asf->file_size_offset = put_pos(pb);
  151. put_le64(pb, 0); /* file size (patched after if not streamed) */
  152. put_le64(pb, 0); /* file time : 1601 :-) */
  153. put_le64(pb, 0x283); /* ??? */
  154. put_le64(pb, 0); /* stream 0 length in us */
  155. put_le64(pb, 0); /* stream 1 length in us */
  156. put_le32(pb, 0x0c1c); /* ??? */
  157. put_le32(pb, 0); /* ??? */
  158. put_le32(pb, 2); /* ??? */
  159. put_le32(pb, asf->packet_size); /* packet size */
  160. put_le32(pb, asf->packet_size); /* ??? */
  161. put_le32(pb, 0x03e800); /* ??? */
  162. /* stream headers */
  163. n = 0;
  164. for(i=0;i<2;i++) {
  165. if (i == 0)
  166. enc = s->audio_enc;
  167. else
  168. enc = s->video_enc;
  169. if (!enc)
  170. continue;
  171. asf->streams[n].num = i;
  172. asf->streams[n].seq = 0;
  173. asf->streams[n].enc = enc;
  174. switch(enc->codec->type) {
  175. case CODEC_TYPE_AUDIO:
  176. asf->audio_stream = &asf->streams[n];
  177. wav_extra_size = 0;
  178. extra_size = 18 + wav_extra_size;
  179. extra_size2 = 0;
  180. break;
  181. default:
  182. case CODEC_TYPE_VIDEO:
  183. asf->video_stream = &asf->streams[n];
  184. wav_extra_size = 0;
  185. extra_size = 0x33;
  186. extra_size2 = 0;
  187. break;
  188. }
  189. put_guid(pb, &stream_header);
  190. put_le64(pb, 24 + 16 * 2 + 22 + extra_size + extra_size2);
  191. if (enc->codec->type == CODEC_TYPE_AUDIO) {
  192. put_guid(pb, &audio_stream);
  193. put_guid(pb, &audio_conceal_none);
  194. } else {
  195. put_guid(pb, &video_stream);
  196. put_guid(pb, &video_conceal_none);
  197. }
  198. put_le64(pb, 0); /* ??? */
  199. put_le32(pb, extra_size); /* wav header len */
  200. put_le32(pb, extra_size2); /* additional data len */
  201. put_le16(pb, n + 1); /* stream number */
  202. put_le32(pb, 0); /* ??? */
  203. if (enc->codec->type == CODEC_TYPE_AUDIO) {
  204. /* WAVEFORMATEX header */
  205. put_le16(pb, 0x55); /* MP3 format */
  206. put_le16(pb, s->audio_enc->channels);
  207. put_le32(pb, s->audio_enc->rate);
  208. put_le32(pb, s->audio_enc->bit_rate / 8);
  209. put_le16(pb, 1); /* block align */
  210. put_le16(pb, 16); /* bits per sample */
  211. put_le16(pb, wav_extra_size);
  212. /* no addtionnal adata */
  213. } else {
  214. put_le32(pb, enc->width);
  215. put_le32(pb, enc->height);
  216. put_byte(pb, 2); /* ??? */
  217. put_le16(pb, 40); /* size */
  218. /* BITMAPINFOHEADER header */
  219. put_le32(pb, 40); /* size */
  220. put_le32(pb, enc->width);
  221. put_le32(pb, enc->height);
  222. put_le16(pb, 1); /* planes */
  223. put_le16(pb, 24); /* depth */
  224. /* compression type */
  225. switch(enc->codec->id) {
  226. case CODEC_ID_H263:
  227. put_tag(pb, "I263");
  228. break;
  229. case CODEC_ID_MJPEG:
  230. put_tag(pb, "MJPG");
  231. break;
  232. default:
  233. put_tag(pb, "XXXX");
  234. break;
  235. }
  236. put_le32(pb, enc->width * enc->height * 3);
  237. put_le32(pb, 0);
  238. put_le32(pb, 0);
  239. put_le32(pb, 0);
  240. put_le32(pb, 0);
  241. }
  242. n++;
  243. }
  244. asf->nb_streams = n;
  245. /* XXX: should media comments */
  246. #if 0
  247. put_guid(pb, &comment_header);
  248. put_le64(pb, 0);
  249. #endif
  250. /* patch the header size fields */
  251. cur_pos = put_pos(pb);
  252. header_size = cur_pos - header_offset;
  253. if (!s->is_streamed) {
  254. header_size += 24 + 6;
  255. put_seek(pb, header_offset - 14, SEEK_SET);
  256. put_le64(pb, header_size);
  257. } else {
  258. header_size += 8 + 50;
  259. put_seek(pb, header_offset - 10, SEEK_SET);
  260. put_le16(pb, header_size);
  261. put_seek(pb, header_offset - 2, SEEK_SET);
  262. put_le16(pb, header_size);
  263. }
  264. put_seek(pb, cur_pos, SEEK_SET);
  265. /* movie chunk, followed by packets of packet_size */
  266. asf->data_offset = cur_pos;
  267. put_guid(pb, &data_header);
  268. put_le64(pb, 24); /* will be patched after */
  269. put_guid(pb, &packet_guid);
  270. put_le64(pb, 0x283); /* ??? */
  271. put_byte(pb, 1); /* ??? */
  272. put_byte(pb, 1); /* ??? */
  273. put_flush_packet(&s->pb);
  274. asf->packet_nb_frames = 0;
  275. asf->packet_timestamp_start = -1;
  276. asf->packet_timestamp_end = -1;
  277. asf->packet_size_left = asf->packet_size - PACKET_HEADER_SIZE;
  278. init_put_byte(&asf->pb, asf->packet_buf, asf->packet_size,
  279. NULL, NULL, NULL);
  280. return 0;
  281. }
  282. /* write a fixed size packet */
  283. static void put_packet(AVFormatContext *s,
  284. unsigned int timestamp, unsigned int duration,
  285. int nb_frames, int padsize)
  286. {
  287. ASFContext *asf = s->priv_data;
  288. PutByteContext *pb = &s->pb;
  289. int flags;
  290. if (s->is_streamed) {
  291. put_chunk(s, 0x4424, asf->packet_size);
  292. }
  293. put_byte(pb, 0x82);
  294. put_le16(pb, 0);
  295. flags = 0x01; /* nb segments present */
  296. if (padsize > 0) {
  297. if (padsize < 256)
  298. flags |= 0x08;
  299. else
  300. flags |= 0x10;
  301. }
  302. put_byte(pb, flags); /* flags */
  303. put_byte(pb, 0x5d);
  304. if (flags & 0x10)
  305. put_le16(pb, padsize);
  306. if (flags & 0x08)
  307. put_byte(pb, padsize);
  308. put_le32(pb, timestamp);
  309. put_le16(pb, duration);
  310. put_byte(pb, nb_frames | 0x80);
  311. }
  312. static void flush_packet(AVFormatContext *s)
  313. {
  314. ASFContext *asf = s->priv_data;
  315. int hdr_size, ptr;
  316. put_packet(s, asf->packet_timestamp_start,
  317. asf->packet_timestamp_end - asf->packet_timestamp_start,
  318. asf->packet_nb_frames, asf->packet_size_left);
  319. /* compute padding */
  320. hdr_size = PACKET_HEADER_SIZE;
  321. if (asf->packet_size_left > 0) {
  322. /* if padding needed, don't forget to count the
  323. padding byte in the header size */
  324. hdr_size++;
  325. asf->packet_size_left--;
  326. /* XXX: I do not test again exact limit to avoid boundary problems */
  327. if (asf->packet_size_left > 200) {
  328. hdr_size++;
  329. asf->packet_size_left--;
  330. }
  331. }
  332. ptr = asf->packet_size - PACKET_HEADER_SIZE - asf->packet_size_left;
  333. memset(asf->packet_buf + ptr, 0, asf->packet_size_left);
  334. put_buffer(&s->pb, asf->packet_buf, asf->packet_size - hdr_size);
  335. put_flush_packet(&s->pb);
  336. asf->packet_nb_frames = 0;
  337. asf->packet_timestamp_start = -1;
  338. asf->packet_timestamp_end = -1;
  339. asf->packet_size_left = asf->packet_size - PACKET_HEADER_SIZE;
  340. init_put_byte(&asf->pb, asf->packet_buf, asf->packet_size,
  341. NULL, NULL, NULL);
  342. }
  343. static void put_frame_header(AVFormatContext *s, ASFStream *stream, int timestamp,
  344. int payload_size, int frag_offset, int frag_len)
  345. {
  346. ASFContext *asf = s->priv_data;
  347. PutByteContext *pb = &asf->pb;
  348. int val;
  349. val = stream->num;
  350. if (stream->enc->key_frame)
  351. val |= 0x80;
  352. put_byte(pb, val);
  353. put_byte(pb, stream->seq);
  354. put_le32(pb, frag_offset); /* fragment offset */
  355. put_byte(pb, 0x08); /* flags */
  356. put_le32(pb, payload_size);
  357. put_le32(pb, timestamp);
  358. put_le16(pb, frag_len);
  359. }
  360. /* Output a frame. We suppose that payload_size <= PACKET_SIZE.
  361. It is there that you understand that the ASF format is really
  362. crap. They have misread the MPEG Systems spec !
  363. */
  364. static void put_frame(AVFormatContext *s, ASFStream *stream, int timestamp,
  365. UINT8 *buf, int payload_size)
  366. {
  367. ASFContext *asf = s->priv_data;
  368. int frag_pos, frag_len, frag_len1;
  369. frag_pos = 0;
  370. while (frag_pos < payload_size) {
  371. frag_len = payload_size - frag_pos;
  372. frag_len1 = asf->packet_size_left - FRAME_HEADER_SIZE;
  373. if (frag_len1 > 0) {
  374. if (frag_len > frag_len1)
  375. frag_len = frag_len1;
  376. put_frame_header(s, stream, timestamp, payload_size, frag_pos, frag_len);
  377. put_buffer(&asf->pb, buf, frag_len);
  378. asf->packet_size_left -= (frag_len + FRAME_HEADER_SIZE);
  379. asf->packet_timestamp_end = timestamp;
  380. if (asf->packet_timestamp_start == -1)
  381. asf->packet_timestamp_start = timestamp;
  382. asf->packet_nb_frames++;
  383. } else {
  384. frag_len = 0;
  385. }
  386. frag_pos += frag_len;
  387. buf += frag_len;
  388. /* output the frame if filled */
  389. if (asf->packet_size_left <= FRAME_HEADER_SIZE)
  390. flush_packet(s);
  391. }
  392. stream->seq++;
  393. }
  394. static int asf_write_audio(AVFormatContext *s, UINT8 *buf, int size)
  395. {
  396. ASFContext *asf = s->priv_data;
  397. int timestamp;
  398. timestamp = (int)((float)s->audio_enc->frame_number * s->audio_enc->frame_size * 1000.0 /
  399. s->audio_enc->rate);
  400. put_frame(s, asf->audio_stream, timestamp, buf, size);
  401. return 0;
  402. }
  403. static int asf_write_video(AVFormatContext *s, UINT8 *buf, int size)
  404. {
  405. ASFContext *asf = s->priv_data;
  406. int timestamp;
  407. timestamp = (int)((float)s->video_enc->frame_number * 1000.0 /
  408. s->video_enc->rate);
  409. put_frame(s, asf->audio_stream, timestamp, buf, size);
  410. return 0;
  411. }
  412. static int asf_write_trailer(AVFormatContext *s)
  413. {
  414. ASFContext *asf = s->priv_data;
  415. long long file_size;
  416. /* flush the current packet */
  417. if (asf->pb.buf_ptr > asf->pb.buffer)
  418. flush_packet(s);
  419. if (s->is_streamed) {
  420. put_chunk(s, 0x4524, 0); /* end of stream */
  421. } else {
  422. /* patch the various place which depends on the file size */
  423. file_size = put_pos(&s->pb);
  424. put_seek(&s->pb, asf->file_size_offset, SEEK_SET);
  425. put_le64(&s->pb, file_size);
  426. put_seek(&s->pb, asf->data_offset + 16, SEEK_SET);
  427. put_le64(&s->pb, file_size - asf->data_offset);
  428. }
  429. put_flush_packet(&s->pb);
  430. free(asf);
  431. return 0;
  432. }
  433. AVFormat asf_format = {
  434. "asf",
  435. "asf format",
  436. "application/octet-stream",
  437. "asf",
  438. CODEC_ID_MP2,
  439. CODEC_ID_MJPEG,
  440. asf_write_header,
  441. asf_write_audio,
  442. asf_write_video,
  443. asf_write_trailer,
  444. };