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

流媒体/Mpeg4/MP4

开发平台:

Unix_Linux

  1. /*
  2.  * Flash Compatible Streaming Format
  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. #include <assert.h>
  25. /* should have a generic way to indicate probable size */
  26. #define DUMMY_FILE_SIZE   (100 * 1024 * 1024)
  27. #define DUMMY_DURATION    600 /* in seconds */
  28. #define TAG_END           0
  29. #define TAG_SHOWFRAME     1
  30. #define TAG_DEFINESHAPE   2
  31. #define TAG_FREECHARACTER 3
  32. #define TAG_PLACEOBJECT   4
  33. #define TAG_REMOVEOBJECT  5
  34. #define TAG_STREAMHEAD    18
  35. #define TAG_STREAMBLOCK   19
  36. #define TAG_JPEG2         21
  37. #define TAG_LONG         0x100
  38. /* flags for shape definition */
  39. #define FLAG_MOVETO      0x01
  40. #define FLAG_SETFILL0    0x02
  41. #define FLAG_SETFILL1    0x04
  42. /* character id used */
  43. #define BITMAP_ID 0
  44. #define SHAPE_ID  1
  45. typedef struct {
  46.     long long duration_pos;
  47.     long long tag_pos;
  48.     int tag;
  49. } SWFContext;
  50. static void put_swf_tag(AVFormatContext *s, int tag)
  51. {
  52.     SWFContext *swf = s->priv_data;
  53.     PutByteContext *pb = &s->pb;
  54.     swf->tag_pos = put_pos(pb);
  55.     swf->tag = tag;
  56.     /* reserve some room for the tag */
  57.     if (tag & TAG_LONG) {
  58.         put_le16(pb, 0);
  59.         put_le32(pb, 0);
  60.     } else {
  61.         put_le16(pb, 0);
  62.     }
  63. }
  64. static void put_swf_end_tag(AVFormatContext *s)
  65. {
  66.     SWFContext *swf = s->priv_data;
  67.     PutByteContext *pb = &s->pb;
  68.     long long pos;
  69.     int tag_len, tag;
  70.     pos = put_pos(pb);
  71.     tag_len = pos - swf->tag_pos - 2;
  72.     tag = swf->tag;
  73.     put_seek(pb, swf->tag_pos, SEEK_SET);
  74.     if (tag & TAG_LONG) {
  75.         tag &= ~TAG_LONG;
  76.         put_le16(pb, (tag << 6) | 0x3f);
  77.         put_le32(pb, tag_len - 4);
  78.     } else {
  79.         assert(tag_len < 0x3f);
  80.         put_le16(pb, (tag << 6) | tag_len);
  81.     }
  82.     put_seek(pb, pos, SEEK_SET);
  83. }
  84. static inline void max_nbits(int *nbits_ptr, int val)
  85. {
  86.     int n;
  87.     if (val == 0)
  88.         return;
  89.     val = abs(val);
  90.     n = 1;
  91.     while (val != 0) {
  92.         n++;
  93.         val >>= 1;
  94.     }
  95.     if (n > *nbits_ptr)
  96.         *nbits_ptr = n;
  97. }
  98. static void put_swf_rect(PutByteContext *pb, 
  99.                          int xmin, int xmax, int ymin, int ymax)
  100. {
  101.     PutBitContext p;
  102.     UINT8 buf[256];
  103.     int nbits, mask;
  104.     init_put_bits(&p, buf, sizeof(buf), NULL, NULL);
  105.     
  106.     nbits = 0;
  107.     max_nbits(&nbits, xmin);
  108.     max_nbits(&nbits, xmax);
  109.     max_nbits(&nbits, ymin);
  110.     max_nbits(&nbits, ymax);
  111.     mask = (1 << nbits) - 1;
  112.     /* rectangle info */
  113.     put_bits(&p, 5, nbits);
  114.     put_bits(&p, nbits, xmin & mask);
  115.     put_bits(&p, nbits, xmax & mask);
  116.     put_bits(&p, nbits, ymin & mask);
  117.     put_bits(&p, nbits, ymax & mask);
  118.     
  119.     flush_put_bits(&p);
  120.     put_buffer(pb, buf, p.buf_ptr - p.buf);
  121. }
  122. static void put_swf_line_edge(PutBitContext *pb, int dx, int dy)
  123. {
  124.     int nbits, mask;
  125.     put_bits(pb, 1, 1); /* edge */
  126.     put_bits(pb, 1, 1); /* line select */
  127.     nbits = 2;
  128.     max_nbits(&nbits, dx);
  129.     max_nbits(&nbits, dy);
  130.     mask = (1 << nbits) - 1;
  131.     put_bits(pb, 4, nbits - 2); /* 16 bits precision */
  132.     if (dx == 0) {
  133.       put_bits(pb, 1, 0); 
  134.       put_bits(pb, 1, 1); 
  135.       put_bits(pb, nbits, dy & mask);
  136.     } else if (dy == 0) {
  137.       put_bits(pb, 1, 0); 
  138.       put_bits(pb, 1, 0); 
  139.       put_bits(pb, nbits, dx & mask);
  140.     } else {
  141.       put_bits(pb, 1, 1); 
  142.       put_bits(pb, nbits, dx & mask);
  143.       put_bits(pb, nbits, dy & mask);
  144.     }
  145. }
  146. #define FRAC_BITS 16
  147. /* put matrix (not size optimized */
  148. static void put_swf_matrix(PutByteContext *pb,
  149.                            int a, int b, int c, int d, int tx, int ty)
  150. {
  151.     PutBitContext p;
  152.     UINT8 buf[256];
  153.     init_put_bits(&p, buf, sizeof(buf), NULL, NULL);
  154.     
  155.     put_bits(&p, 1, 1); /* a, d present */
  156.     put_bits(&p, 5, 20); /* nb bits */
  157.     put_bits(&p, 20, a);
  158.     put_bits(&p, 20, d);
  159.     
  160.     put_bits(&p, 1, 1); /* b, c present */
  161.     put_bits(&p, 5, 20); /* nb bits */
  162.     put_bits(&p, 20, c);
  163.     put_bits(&p, 20, b);
  164.     put_bits(&p, 5, 20); /* nb bits */
  165.     put_bits(&p, 20, tx);
  166.     put_bits(&p, 20, ty);
  167.     flush_put_bits(&p);
  168.     put_buffer(pb, buf, p.buf_ptr - p.buf);
  169. }
  170. static int swf_write_header(AVFormatContext *s)
  171. {
  172.     SWFContext *swf;
  173.     PutByteContext *pb = &s->pb;
  174.     AVEncodeContext *enc = s->video_enc;
  175.     PutBitContext p;
  176.     UINT8 buf1[256];
  177.     swf = malloc(sizeof(SWFContext));
  178.     if (!swf)
  179.         return -1;
  180.     s->priv_data = swf;
  181.     put_tag(pb, "FWS");
  182.     put_byte(pb, 3); /* version (should use 4 for mpeg audio support) */
  183.     put_le32(pb, DUMMY_FILE_SIZE); /* dummy size 
  184.                                       (will be patched if not streamed) */ 
  185.     put_swf_rect(pb, 0, enc->width, 0, enc->height);
  186.     put_le16(pb, enc->rate << 8); /* frame rate */
  187.     swf->duration_pos = put_pos(pb);
  188.     put_le16(pb, DUMMY_DURATION * enc->rate); /* frame count */
  189.     
  190.     /* define a shape with the jpeg inside */
  191.     put_swf_tag(s, TAG_DEFINESHAPE);
  192.     put_le16(pb, SHAPE_ID); /* ID of shape */
  193.     /* bounding rectangle */
  194.     put_swf_rect(pb, 0, enc->width, 0, enc->height);
  195.     /* style info */
  196.     put_byte(pb, 1); /* one fill style */
  197.     put_byte(pb, 0x41); /* clipped bitmap fill */
  198.     put_le16(pb, BITMAP_ID); /* bitmap ID */
  199.     /* position of the bitmap */
  200.     put_swf_matrix(pb, (int)(1.0 * (1 << FRAC_BITS)), 0, 
  201.                    0, (int)(1.0 * (1 << FRAC_BITS)), 0, 0);
  202.     put_byte(pb, 0); /* no line style */
  203.     
  204.     /* shape drawing */
  205.     init_put_bits(&p, buf1, sizeof(buf1), NULL, NULL);
  206.     put_bits(&p, 4, 1); /* one fill bit */
  207.     put_bits(&p, 4, 0); /* zero line bit */
  208.     
  209.     put_bits(&p, 1, 0); /* not an edge */
  210.     put_bits(&p, 5, FLAG_MOVETO | FLAG_SETFILL0);
  211.     put_bits(&p, 5, 1); /* nbits */
  212.     put_bits(&p, 1, 0); /* X */
  213.     put_bits(&p, 1, 0); /* Y */
  214.     put_bits(&p, 1, 1); /* set fill style 1 */
  215.     
  216.     /* draw the rectangle ! */
  217.     put_swf_line_edge(&p, enc->width, 0);
  218.     put_swf_line_edge(&p, 0, enc->height);
  219.     put_swf_line_edge(&p, -enc->width, 0);
  220.     put_swf_line_edge(&p, 0, -enc->height);
  221.     
  222.     /* end of shape */
  223.     put_bits(&p, 1, 0); /* not an edge */
  224.     put_bits(&p, 5, 0);
  225.     flush_put_bits(&p);
  226.     put_buffer(pb, buf1, p.buf_ptr - p.buf);
  227.     put_swf_end_tag(s);
  228.     
  229.     if (s->audio_enc) {
  230.         int v;
  231.         /* start sound */
  232.         v = 0;
  233.         switch(s->audio_enc->rate) {
  234.         case 11025:
  235.             v |= 1 << 2;
  236.             break;
  237.         case 22050:
  238.             v |= 2 << 2;
  239.             break;
  240.         case 44100:
  241.             v |= 3 << 2;
  242.             break;
  243.         default:
  244.             /* not supported */
  245.             free(swf);
  246.             return -1;
  247.         }
  248.         if (s->audio_enc->channels == 2)
  249.             v |= 1;
  250.         v |= 0x20; /* mp3 compressed */
  251.         v |= 0x02; /* 16 bits */
  252.         
  253.         put_swf_tag(s, TAG_STREAMHEAD);
  254.         put_byte(&s->pb, 0);
  255.         put_byte(&s->pb, v);
  256.         put_le16(&s->pb, s->audio_enc->rate / s->video_enc->rate); /* avg samples per frame */
  257.         
  258.         put_swf_end_tag(s);
  259.     }
  260.     put_flush_packet(&s->pb);
  261.     return 0;
  262. }
  263. static int swf_write_video(AVFormatContext *s, UINT8 *buf, int size)
  264. {
  265.     PutByteContext *pb = &s->pb;
  266.     AVEncodeContext *enc = s->video_enc;
  267.     static int tag_id = 0;
  268.     if (enc->frame_number > 1) {
  269.         /* remove the shape */
  270.         put_swf_tag(s, TAG_REMOVEOBJECT);
  271.         put_le16(pb, SHAPE_ID); /* shape ID */
  272.         put_le16(pb, 1); /* depth */
  273.         put_swf_end_tag(s);
  274.         
  275.         /* free the bitmap */
  276.         put_swf_tag(s, TAG_FREECHARACTER);
  277.         put_le16(pb, BITMAP_ID);
  278.         put_swf_end_tag(s);
  279.     }
  280.     put_swf_tag(s, TAG_JPEG2 | TAG_LONG);
  281.     put_le16(pb, tag_id); /* ID of the image */
  282.     /* a dummy jpeg header seems to be required */
  283.     put_byte(pb, 0xff); 
  284.     put_byte(pb, 0xd8);
  285.     put_byte(pb, 0xff);
  286.     put_byte(pb, 0xd9);
  287.     /* write the jpeg image */
  288.     put_buffer(pb, buf, size);
  289.     put_swf_end_tag(s);
  290.     /* draw the shape */
  291.     put_swf_tag(s, TAG_PLACEOBJECT);
  292.     put_le16(pb, SHAPE_ID); /* shape ID */
  293.     put_le16(pb, 1); /* depth */
  294.     put_swf_matrix(pb, 1 << FRAC_BITS, 0, 0, 1 << FRAC_BITS, 0, 0);
  295.     put_swf_end_tag(s);
  296.     
  297.     /* output the frame */
  298.     put_swf_tag(s, TAG_SHOWFRAME);
  299.     put_swf_end_tag(s);
  300.     
  301.     put_flush_packet(&s->pb);
  302.     return 0;
  303. }
  304. static int swf_write_audio(AVFormatContext *s, UINT8 *buf, int size)
  305. {
  306.     PutByteContext *pb = &s->pb;
  307.     put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG);
  308.     put_buffer(pb, buf, size);
  309.     
  310.     put_swf_end_tag(s);
  311.     put_flush_packet(&s->pb);
  312.     return 0;
  313. }
  314. static int swf_write_trailer(AVFormatContext *s)
  315. {
  316.     SWFContext *swf = s->priv_data;
  317.     PutByteContext *pb = &s->pb;
  318.     int file_size;
  319.     AVEncodeContext *enc = s->video_enc;
  320.     put_swf_tag(s, TAG_END);
  321.     put_swf_end_tag(s);
  322.     
  323.     put_flush_packet(&s->pb);
  324.     /* patch file size and number of frames if not streamed */
  325.     if (!s->is_streamed) {
  326.         file_size = put_pos(pb);
  327.         put_seek(pb, 4, SEEK_SET);
  328.         put_le32(pb, file_size);
  329.         put_seek(pb, swf->duration_pos, SEEK_SET);
  330.         put_le16(pb, enc->frame_number);
  331.     }
  332.     free(swf);
  333.     return 0;
  334. }
  335. AVFormat swf_format = {
  336.     "swf",
  337.     "Flash format",
  338.     "application/x-shockwave-flash",
  339.     "swf",
  340.     CODEC_ID_MP2,
  341.     CODEC_ID_MJPEG,
  342.     swf_write_header,
  343.     swf_write_audio,
  344.     swf_write_video,
  345.     swf_write_trailer,
  346. };