asfenc.c
上传用户:jxp0626
上传日期:2007-01-08
资源大小:102k
文件大小:14k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Unix_Linux

  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 seqno;
  34.     int packet_size;
  35.     ASFStream streams[2];
  36.     ASFStream *audio_stream, *video_stream;
  37.     int nb_streams;
  38.     /* non streamed additonnal info */
  39.     int file_size_offset;
  40.     int data_offset;
  41.     /* packet filling */
  42.     int packet_size_left;
  43.     int packet_timestamp_start;
  44.     int packet_timestamp_end;
  45.     int packet_nb_frames;
  46.     UINT8 packet_buf[PACKET_SIZE];
  47.     PutByteContext pb;
  48. } ASFContext;
  49. typedef struct {
  50.     UINT32 v1;
  51.     UINT16 v2;
  52.     UINT16 v3;
  53.     UINT8 v4[8];
  54. } GUID;
  55. static const GUID asf_header = {
  56.     0x75B22630, 0x668E, 0x11CF, { 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C },
  57. };
  58. static const GUID file_header = {
  59.     0x8CABDCA1, 0xA947, 0x11CF, { 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 },
  60. };
  61. static const GUID stream_header = {
  62.     0xB7DC0791, 0xA9B7, 0x11CF, { 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 },
  63. };
  64. static const GUID audio_stream = {
  65.     0xF8699E40, 0x5B4D, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B },
  66. };
  67. static const GUID audio_conceal_none = {
  68.     0x49f1a440, 0x4ece, 0x11d0, { 0xa3, 0xac, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6 },
  69. };
  70. static const GUID video_stream = {
  71.     0xBC19EFC0, 0x5B4D, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B },
  72. };
  73. static const GUID video_conceal_none = {
  74.     0x20FB5700, 0x5B55, 0x11CF, { 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B },
  75. };
  76. static const GUID comment_header = {
  77.     0x86D15240, 0x311D, 0x11D0, { 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 },
  78. };
  79. static const GUID data_header = {
  80.     0x75b22636, 0x668e, 0x11cf, { 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c },
  81. };
  82. static const GUID packet_guid = {
  83.     0xF656CCE1, 0x03B3, 0x11D4, { 0xBE, 0xA2, 0x00, 0xA0, 0xCC, 0x3D, 0x72, 0x74 },
  84. };
  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.     
  146.     /* file header */
  147.     header_offset = put_pos(pb);
  148.     put_guid(pb, &file_header);
  149.     put_le64(pb, 24 + 80);
  150.     put_guid(pb, &my_guid);
  151.     asf->file_size_offset = put_pos(pb);
  152.     put_le64(pb, 0); /* file size (patched after if not streamed) */
  153.     put_le64(pb, 0); /* file time : 1601 :-) */
  154.     put_le64(pb, 0x283); /* ??? */
  155.     put_le64(pb, 0); /* stream 0 length in us */
  156.     put_le64(pb, 0); /* stream 1 length in us */
  157.     put_le32(pb, 0x0c1c); /* ??? */
  158.     put_le32(pb, 0); /* ??? */
  159.     put_le32(pb, 2); /* ??? */
  160.     put_le32(pb, asf->packet_size); /* packet size */
  161.     put_le32(pb, asf->packet_size); /* ??? */
  162.     put_le32(pb, 0x03e800); /* ??? */
  163.     
  164.     /* stream headers */
  165.     n = 0;
  166.     for(i=0;i<2;i++) {
  167.         if (i == 0)
  168.             enc = s->audio_enc;
  169.         else
  170.             enc = s->video_enc;
  171.         
  172.         if (!enc)
  173.             continue;
  174.         asf->streams[n].num = n + 1;
  175.         asf->streams[n].seq = 0;
  176.         asf->streams[n].enc = enc;
  177.         
  178.         switch(enc->codec->type) {
  179.         case CODEC_TYPE_AUDIO:
  180.             asf->audio_stream = &asf->streams[n];
  181.             wav_extra_size = 0;
  182.             extra_size = 18 + wav_extra_size;
  183.             extra_size2 = 0;
  184.             break;
  185.         default:
  186.         case CODEC_TYPE_VIDEO:
  187.             asf->video_stream = &asf->streams[n];
  188.             wav_extra_size = 0;
  189.             extra_size = 0x33;
  190.             extra_size2 = 0;
  191.             break;
  192.         }
  193.         put_guid(pb, &stream_header);
  194.         put_le64(pb, 24 + 16 * 2 + 22 + extra_size + extra_size2);
  195.         if (enc->codec->type == CODEC_TYPE_AUDIO) {
  196.             put_guid(pb, &audio_stream);
  197.             put_guid(pb, &audio_conceal_none);
  198.         } else {
  199.             put_guid(pb, &video_stream);
  200.             put_guid(pb, &video_conceal_none);
  201.         }
  202.         put_le64(pb, 0); /* ??? */
  203.         put_le32(pb, extra_size); /* wav header len */
  204.         put_le32(pb, extra_size2); /* additional data len */
  205.         put_le16(pb, n + 1); /* stream number */
  206.         put_le32(pb, 0); /* ??? */
  207.         
  208.         if (enc->codec->type == CODEC_TYPE_AUDIO) {
  209.             /* WAVEFORMATEX header */
  210.             put_wav_header(pb, enc);
  211.         } else {
  212.             put_le32(pb, enc->width);
  213.             put_le32(pb, enc->height);
  214.             put_byte(pb, 2); /* ??? */
  215.             put_le16(pb, 40); /* size */
  216.             /* BITMAPINFOHEADER header */
  217.             put_bmp_header(pb, enc);
  218.         }
  219.         n++;
  220.     }
  221.     asf->nb_streams = n;
  222.     /* XXX: should put media comments */
  223. #if 0
  224.     put_guid(pb, &comment_header);
  225.     put_le64(pb, 0);
  226. #endif
  227.     /* patch the header size fields */
  228.     cur_pos = put_pos(pb);
  229.     header_size = cur_pos - header_offset;
  230.     if (!s->is_streamed) {
  231.         header_size += 24 + 6;
  232.         put_seek(pb, header_offset - 14, SEEK_SET);
  233.         put_le64(pb, header_size);
  234.     } else {
  235.         header_size += 8 + 50;
  236.         put_seek(pb, header_offset - 10, SEEK_SET);
  237.         put_le16(pb, header_size);
  238.         put_seek(pb, header_offset - 2, SEEK_SET);
  239.         put_le16(pb, header_size);
  240.     }
  241.     put_seek(pb, cur_pos, SEEK_SET);
  242.     /* movie chunk, followed by packets of packet_size */
  243.     asf->data_offset = cur_pos;
  244.     put_guid(pb, &data_header);
  245.     put_le64(pb, 24); /* will be patched after */
  246.     put_guid(pb, &packet_guid);
  247.     put_le64(pb, 0x283); /* ??? */
  248.     put_byte(pb, 1); /* ??? */
  249.     put_byte(pb, 1); /* ??? */
  250.     put_flush_packet(&s->pb);
  251.     asf->packet_nb_frames = 0;
  252.     asf->packet_timestamp_start = -1;
  253.     asf->packet_timestamp_end = -1;
  254.     asf->packet_size_left = asf->packet_size - PACKET_HEADER_SIZE;
  255.     init_put_byte(&asf->pb, asf->packet_buf, asf->packet_size,
  256.                   NULL, NULL, NULL);
  257.     return 0;
  258. }
  259. /* write a fixed size packet */
  260. static void put_packet(AVFormatContext *s, 
  261.                        unsigned int timestamp, unsigned int duration, 
  262.                        int nb_frames, int padsize)
  263. {
  264.     ASFContext *asf = s->priv_data;
  265.     PutByteContext *pb = &s->pb;
  266.     int flags;
  267.     if (s->is_streamed) {
  268.         put_chunk(s, 0x4424, asf->packet_size);
  269.     }
  270.     put_byte(pb, 0x82);
  271.     put_le16(pb, 0);
  272.     
  273.     flags = 0x01; /* nb segments present */
  274.     if (padsize > 0) {
  275.         if (padsize < 256)
  276.             flags |= 0x08;
  277.         else
  278.             flags |= 0x10;
  279.     }
  280.     put_byte(pb, flags); /* flags */
  281.     put_byte(pb, 0x5d);
  282.     if (flags & 0x10)
  283.         put_le16(pb, padsize);
  284.     if (flags & 0x08)
  285.         put_byte(pb, padsize);
  286.     put_le32(pb, timestamp);
  287.     put_le16(pb, duration);
  288.     put_byte(pb, nb_frames | 0x80);
  289. }
  290. static void flush_packet(AVFormatContext *s)
  291. {
  292.     ASFContext *asf = s->priv_data;
  293.     int hdr_size, ptr;
  294.     
  295.     put_packet(s, asf->packet_timestamp_start, 
  296.                asf->packet_timestamp_end - asf->packet_timestamp_start, 
  297.                asf->packet_nb_frames, asf->packet_size_left);
  298.     
  299.     /* compute padding */
  300.     hdr_size = PACKET_HEADER_SIZE;
  301.     if (asf->packet_size_left > 0) {
  302.         /* if padding needed, don't forget to count the
  303.            padding byte in the header size */
  304.         hdr_size++;
  305.         asf->packet_size_left--;
  306.         /* XXX: I do not test again exact limit to avoid boundary problems */
  307.         if (asf->packet_size_left > 200) {
  308.             hdr_size++;
  309.             asf->packet_size_left--;
  310.         }
  311.     }
  312.     ptr = asf->packet_size - PACKET_HEADER_SIZE - asf->packet_size_left;
  313.     memset(asf->packet_buf + ptr, 0, asf->packet_size_left);
  314.     
  315.     put_buffer(&s->pb, asf->packet_buf, asf->packet_size - hdr_size);
  316.     
  317.     put_flush_packet(&s->pb);
  318.     asf->packet_nb_frames = 0;
  319.     asf->packet_timestamp_start = -1;
  320.     asf->packet_timestamp_end = -1;
  321.     asf->packet_size_left = asf->packet_size - PACKET_HEADER_SIZE;
  322.     init_put_byte(&asf->pb, asf->packet_buf, asf->packet_size,
  323.                   NULL, NULL, NULL);
  324. }
  325. static void put_frame_header(AVFormatContext *s, ASFStream *stream, int timestamp,
  326.                              int payload_size, int frag_offset, int frag_len)
  327. {
  328.     ASFContext *asf = s->priv_data;
  329.     PutByteContext *pb = &asf->pb;
  330.     int val;
  331.     val = stream->num;
  332.     if (stream->enc->key_frame)
  333.         val |= 0x80;
  334.     put_byte(pb, val);
  335.     put_byte(pb, stream->seq);
  336.     put_le32(pb, frag_offset); /* fragment offset */
  337.     put_byte(pb, 0x08); /* flags */
  338.     put_le32(pb, payload_size);
  339.     put_le32(pb, timestamp);
  340.     put_le16(pb, frag_len);
  341. }
  342. /* Output a frame. We suppose that payload_size <= PACKET_SIZE.
  343.    It is there that you understand that the ASF format is really
  344.    crap. They have misread the MPEG Systems spec ! 
  345.  */
  346. static void put_frame(AVFormatContext *s, ASFStream *stream, int timestamp,
  347.                       UINT8 *buf, int payload_size)
  348. {
  349.     ASFContext *asf = s->priv_data;
  350.     int frag_pos, frag_len, frag_len1;
  351.     
  352.     frag_pos = 0;
  353.     while (frag_pos < payload_size) {
  354.         frag_len = payload_size - frag_pos;
  355.         frag_len1 = asf->packet_size_left - FRAME_HEADER_SIZE;
  356.         if (frag_len1 > 0) {
  357.             if (frag_len > frag_len1)
  358.                 frag_len = frag_len1;
  359.             put_frame_header(s, stream, timestamp, payload_size, frag_pos, frag_len);
  360.             put_buffer(&asf->pb, buf, frag_len);
  361.             asf->packet_size_left -= (frag_len + FRAME_HEADER_SIZE);
  362.             asf->packet_timestamp_end = timestamp;
  363.             if (asf->packet_timestamp_start == -1)
  364.                 asf->packet_timestamp_start = timestamp;
  365.             asf->packet_nb_frames++;
  366.         } else {
  367.             frag_len = 0;
  368.         }
  369.         frag_pos += frag_len;
  370.         buf += frag_len;
  371.         /* output the frame if filled */
  372.         if (asf->packet_size_left <= FRAME_HEADER_SIZE)
  373.             flush_packet(s);
  374.     }
  375.     stream->seq++;
  376. }
  377. static int asf_write_audio(AVFormatContext *s, UINT8 *buf, int size)
  378. {
  379.     ASFContext *asf = s->priv_data;
  380.     int timestamp;
  381.     timestamp = (int)((float)s->audio_enc->frame_number * s->audio_enc->frame_size * 1000.0 / 
  382.                       s->audio_enc->rate);
  383.     put_frame(s, asf->audio_stream, timestamp, buf, size);
  384.     return 0;
  385. }
  386. static int asf_write_video(AVFormatContext *s, UINT8 *buf, int size)
  387. {
  388.     ASFContext *asf = s->priv_data;
  389.     int timestamp;
  390.     timestamp = (int)((float)s->video_enc->frame_number * 1000.0 / 
  391.                       s->video_enc->rate);
  392.     put_frame(s, asf->video_stream, timestamp, buf, size);
  393.     return 0;
  394. }
  395. static int asf_write_trailer(AVFormatContext *s)
  396. {
  397.     ASFContext *asf = s->priv_data;
  398.     long long file_size;
  399.     /* flush the current packet */
  400.     if (asf->pb.buf_ptr > asf->pb.buffer)
  401.         flush_packet(s);
  402.     if (s->is_streamed) {
  403.         put_chunk(s, 0x4524, 0); /* end of stream */
  404.     } else {
  405.         /* patch the various place which depends on the file size */
  406.         file_size = put_pos(&s->pb);
  407.         put_seek(&s->pb, asf->file_size_offset, SEEK_SET);
  408.         put_le64(&s->pb, file_size);
  409.         put_seek(&s->pb, asf->data_offset + 16, SEEK_SET);
  410.         put_le64(&s->pb, file_size - asf->data_offset);
  411.     }
  412.     put_flush_packet(&s->pb);
  413.     free(asf);
  414.     return 0;
  415. }
  416. AVFormat asf_format = {
  417.     "asf",
  418.     "asf format",
  419.     "application/octet-stream",
  420.     "asf",
  421.     CODEC_ID_MP2,
  422.     CODEC_ID_DIVX,
  423.     asf_write_header,
  424.     asf_write_audio,
  425.     asf_write_video,
  426.     asf_write_trailer,
  427. };