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

流媒体/Mpeg4/MP4

开发平台:

Unix_Linux

  1. /*
  2.  * RV 1.0 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. /* in ms */
  25. #define BUFFER_DURATION 0 
  26. typedef struct {
  27.     int nb_packets;
  28.     int packet_total_size;
  29.     int packet_max_size;
  30.     /* codec related output */
  31.     int bit_rate;
  32.     float frame_rate;
  33.     int nb_frames;    /* current frame number */
  34.     int total_frames; /* total number of frames */
  35.     int num;
  36.     AVEncodeContext *enc;
  37. } StreamInfo;
  38. typedef struct {
  39.     StreamInfo streams[2];
  40.     StreamInfo *audio_stream, *video_stream;
  41.     int nb_streams;
  42.     int data_pos; /* position of the data after the header */
  43. } RMContext;
  44. static void put_long(PutByteContext *s, unsigned int val)
  45. {
  46.     put_byte(s, val >> 24);
  47.     put_byte(s, val >> 16);
  48.     put_byte(s, val >> 8);
  49.     put_byte(s, val);
  50. }
  51. static void put_short(PutByteContext *s, unsigned int val)
  52. {
  53.     put_byte(s, val >> 8);
  54.     put_byte(s, val);
  55. }
  56. static void put_str(PutByteContext *s, const char *tag)
  57. {
  58.     put_short(s,strlen(tag));
  59.     while (*tag) {
  60.         put_byte(s, *tag++);
  61.     }
  62. }
  63. static void put_str8(PutByteContext *s, const char *tag)
  64. {
  65.     put_byte(s, strlen(tag));
  66.     while (*tag) {
  67.         put_byte(s, *tag++);
  68.     }
  69. }
  70. int find_tag(const char *tag, char *buf, int buf_size, const char *str)
  71. {
  72.     int len = strlen(tag);
  73.     char *q;
  74.     buf[0] = '';
  75.     while (*str) {
  76.         if (*str == '+' && !strncmp(str + 1, tag, len) && str[len+1] == '=') {
  77.             str += len + 2;
  78.             q = buf;
  79.             while (*str && *str != '+' && (q - buf) < (buf_size - 1)) {
  80.                 *q++ = *str++;
  81.             }
  82.             /* remove trailing spaces */
  83.             while (q > buf && q[-1] == ' ') q--;
  84.             *q = '';
  85.             return 1;
  86.         }
  87.         str++;
  88.     }
  89.     return 0;
  90. }
  91. static void rv10_write_header(AVFormatContext *ctx, 
  92.                               int data_size, int index_pos)
  93. {
  94.     RMContext *rm = ctx->priv_data;
  95.     PutByteContext *s = &ctx->pb;
  96.     StreamInfo *stream;
  97.     unsigned char *data_offset_ptr, *start_ptr;
  98.     char title[1024], author[1024], copyright[1024], comment[1024];
  99.     const char *desc, *mimetype;
  100.     int nb_packets, packet_total_size, packet_max_size, size, packet_avg_size, i;
  101.     int bit_rate, v, duration, flags, data_pos;
  102.     start_ptr = s->buf_ptr;
  103.     put_tag(s, ".RMF");
  104.     put_long(s,18); /* header size */
  105.     put_short(s,0);
  106.     put_long(s,0);
  107.     put_long(s,4 + rm->nb_streams); /* num headers */
  108.     put_tag(s,"PROP");
  109.     put_long(s, 50);
  110.     put_short(s, 0);
  111.     packet_max_size = 0;
  112.     packet_total_size = 0;
  113.     nb_packets = 0;
  114.     bit_rate = 0;
  115.     duration = 0;
  116.     for(i=0;i<rm->nb_streams;i++) {
  117.         StreamInfo *stream = &rm->streams[i];
  118.         bit_rate += stream->bit_rate;
  119.         if (stream->packet_max_size > packet_max_size)
  120.             packet_max_size = stream->packet_max_size;
  121.         nb_packets += stream->nb_packets;
  122.         packet_total_size += stream->packet_total_size;
  123.         /* select maximum duration */
  124.         v = (int) (1000.0 * (float)stream->total_frames / stream->frame_rate);
  125.         if (v > duration)
  126.             duration = v;
  127.     }
  128.     put_long(s, bit_rate); /* max bit rate */
  129.     put_long(s, bit_rate); /* avg bit rate */
  130.     put_long(s, packet_max_size);        /* max packet size */
  131.     if (nb_packets > 0)
  132.         packet_avg_size = packet_total_size / nb_packets;
  133.     else
  134.         packet_avg_size = 0;
  135.     put_long(s, packet_avg_size);        /* avg packet size */
  136.     put_long(s, nb_packets);  /* num packets */
  137.     put_long(s, duration); /* duration */
  138.     put_long(s, BUFFER_DURATION);           /* preroll */
  139.     put_long(s, index_pos);           /* index offset */
  140.     /* computation of data the data offset */
  141.     data_offset_ptr = s->buf_ptr;
  142.     put_long(s, 0);           /* data offset : will be patched after */
  143.     put_short(s, rm->nb_streams);    /* num streams */
  144.     flags = 1 | 2; /* save allowed & perfect play */
  145.     if (ctx->is_streamed)
  146.         flags |= 4; /* live broadcast */
  147.     put_short(s, flags);
  148.     
  149.     /* comments */
  150.     find_tag("title", title, sizeof(title), comment_string);
  151.     find_tag("author", author, sizeof(author), comment_string);
  152.     find_tag("copyright", copyright, sizeof(copyright), comment_string);
  153.     find_tag("comment", comment, sizeof(comment), comment_string);
  154.     put_tag(s,"CONT");
  155.     size = strlen(title) + strlen(author) + strlen(copyright) + strlen(comment) + 
  156.         4 * 2 + 10;
  157.     put_long(s,size);
  158.     put_short(s,0);
  159.     put_str(s, title);
  160.     put_str(s, author);
  161.     put_str(s, copyright);
  162.     put_str(s, comment);
  163.     
  164.     for(i=0;i<rm->nb_streams;i++) {
  165.         int codec_data_size;
  166.         stream = &rm->streams[i];
  167.         
  168.         if (stream->enc->codec->type == CODEC_TYPE_AUDIO) {
  169.             desc = "The Audio Stream";
  170.             mimetype = "audio/x-pn-realaudio";
  171.             codec_data_size = 73;
  172.         } else {
  173.             desc = "The Video Stream";
  174.             mimetype = "video/x-pn-realvideo";
  175.             codec_data_size = 34;
  176.         }
  177.         put_tag(s,"MDPR");
  178.         size = 10 + 9 * 4 + strlen(desc) + strlen(mimetype) + codec_data_size;
  179.         put_long(s, size);
  180.         put_short(s, 0);
  181.         put_short(s, i); /* stream number */
  182.         put_long(s, stream->bit_rate); /* max bit rate */
  183.         put_long(s, stream->bit_rate); /* avg bit rate */
  184.         put_long(s, stream->packet_max_size);        /* max packet size */
  185.         if (stream->nb_packets > 0)
  186.             packet_avg_size = stream->packet_total_size / 
  187.                 stream->nb_packets;
  188.         else
  189.             packet_avg_size = 0;
  190.         put_long(s, packet_avg_size);        /* avg packet size */
  191.         put_long(s, 0);           /* start time */
  192.         put_long(s, BUFFER_DURATION);           /* preroll */
  193.         /* duration */
  194.         put_long(s, (int)(stream->total_frames * 1000 / stream->frame_rate));
  195.         put_str8(s, desc);
  196.         put_str8(s, mimetype);
  197.         put_long(s, codec_data_size);
  198.         
  199.         if (stream->enc->codec->type == CODEC_TYPE_AUDIO) {
  200.             int coded_frame_size, fscode, sample_rate;
  201.             sample_rate = stream->enc->rate;
  202.             coded_frame_size = (stream->enc->bit_rate * 
  203.                                 stream->enc->frame_size) / (8 * sample_rate);
  204.             /* audio codec info */
  205.             put_tag(s, ".ra");
  206.             put_byte(s, 0xfd);
  207.             put_long(s, 0x00040000); /* version */
  208.             put_tag(s, ".ra4");
  209.             put_long(s, 0x01b53530); /* stream length */
  210.             put_short(s, 4); /* unknown */
  211.             put_long(s, 0x39); /* header size */
  212.             switch(sample_rate) {
  213.             case 48000:
  214.             case 24000:
  215.             case 12000:
  216.                 fscode = 1;
  217.                 break;
  218.             default:
  219.             case 44100:
  220.             case 22050:
  221.             case 11025:
  222.                 fscode = 2;
  223.                 break;
  224.             case 32000:
  225.             case 16000:
  226.             case 8000:
  227.                 fscode = 3;
  228.             }
  229.             put_short(s, fscode); /* codec additional info, for AC3, seems
  230.                                      to be a frequency code */
  231.             /* special hack to compensate rounding errors... */
  232.             if (coded_frame_size == 557)
  233.                 coded_frame_size--;
  234.             put_long(s, coded_frame_size); /* frame length */
  235.             put_long(s, 0x51540); /* unknown */
  236.             put_long(s, 0x249f0); /* unknown */
  237.             put_long(s, 0x249f0); /* unknown */
  238.             put_short(s, 0x01);
  239.             /* frame length : seems to be very important */
  240.             put_short(s, coded_frame_size); 
  241.             put_long(s, 0); /* unknown */
  242.             put_short(s, stream->enc->rate); /* sample rate */
  243.             put_long(s, 0x10); /* unknown */
  244.             put_short(s, stream->enc->channels);
  245.             put_str8(s, "Int0"); /* codec name */
  246.             put_str8(s, "dnet"); /* codec name */
  247.             put_short(s, 0); /* title length */
  248.             put_short(s, 0); /* author length */
  249.             put_short(s, 0); /* copyright length */
  250.             put_byte(s, 0); /* end of header */
  251.         } else {
  252.             /* video codec info */
  253.             put_long(s,34); /* size */
  254.             put_tag(s,"VIDORV10");
  255.             put_short(s, stream->enc->width);
  256.             put_short(s, stream->enc->height);
  257.             put_short(s, 24); /* frames per seconds ? */
  258.             put_long(s,0);     /* unknown meaning */
  259.             put_short(s, 12);  /* unknown meaning */
  260.             put_long(s,0);     /* unknown meaning */
  261.             put_short(s, 8);    /* unknown meaning */
  262.             /* Seems to be the codec version: only use basic H263. The next
  263.                versions seems to add a diffential DC coding as in
  264.                MPEG... nothing new under the sun */
  265.             put_long(s,0x10000000); 
  266.             //put_long(s,0x10003000); 
  267.         }
  268.     }
  269.     /* patch data offset field */
  270.     data_pos = s->buf_ptr - start_ptr;
  271.     rm->data_pos = data_pos;
  272.     data_offset_ptr[0] = data_pos >> 24;
  273.     data_offset_ptr[1] = data_pos >> 16;
  274.     data_offset_ptr[2] = data_pos >> 8;
  275.     data_offset_ptr[3] = data_pos;
  276.     
  277.     /* data stream */
  278.     put_tag(s,"DATA");
  279.     put_long(s,data_size + 10 + 8);
  280.     put_short(s,0);
  281.     put_long(s, nb_packets); /* number of packets */
  282.     put_long(s,0); /* next data header */
  283. }
  284. static void write_packet_header(AVFormatContext *ctx, StreamInfo *stream, 
  285.                                 int length, int key_frame)
  286. {
  287.     int timestamp;
  288.     PutByteContext *s = &ctx->pb;
  289.     stream->nb_packets++;
  290.     stream->packet_total_size += length;
  291.     if (length > stream->packet_max_size)
  292.         stream->packet_max_size =  length;
  293.     put_short(s,0); /* version */
  294.     put_short(s,length + 12);
  295.     put_short(s, stream->num); /* stream number */
  296.     timestamp = (1000 * (float)stream->nb_frames) / stream->frame_rate;
  297.     put_long(s, timestamp); /* timestamp */
  298.     put_byte(s, 0); /* reserved */
  299.     put_byte(s, key_frame ? 2 : 0); /* flags */
  300. }
  301. static int rm_write_header(AVFormatContext *s)
  302. {
  303.     StreamInfo *stream;
  304.     RMContext *rm;
  305.     int n;
  306.     rm = malloc(sizeof(RMContext));
  307.     if (!rm)
  308.         return -1;
  309.     memset(rm, 0, sizeof(RMContext));
  310.     s->priv_data = rm;
  311.     n = 0;
  312.     if (s->audio_enc) {
  313.         stream = &rm->streams[n];
  314.         memset(stream, 0, sizeof(StreamInfo));
  315.         stream->num = n;
  316.         rm->audio_stream = stream;
  317.         stream->bit_rate = s->audio_enc->bit_rate;
  318.         stream->frame_rate = (float)s->audio_enc->rate / (float)s->audio_enc->frame_size;
  319.         stream->enc = s->audio_enc;
  320.         /* XXX: dummy values */
  321.         stream->packet_max_size = 1024;
  322.         stream->nb_packets = 1000;
  323.         stream->total_frames = stream->nb_packets;
  324.         n++;
  325.     }
  326.     if (s->video_enc) {
  327.         stream = &rm->streams[n];
  328.         memset(stream, 0, sizeof(StreamInfo));
  329.         stream->num = n;
  330.         rm->video_stream = stream;
  331.         stream->bit_rate = s->video_enc->bit_rate;
  332.         stream->frame_rate = s->video_enc->rate;
  333.         stream->enc = s->video_enc;
  334.         /* XXX: dummy values */
  335.         stream->packet_max_size = 4096;
  336.         stream->nb_packets = 1000;
  337.         stream->total_frames = stream->nb_packets;
  338.         n++;
  339.     }
  340.     rm->nb_streams = n;
  341.     rv10_write_header(s, 0, 0);
  342.     put_flush_packet(&s->pb);
  343.     return 0;
  344. }
  345. static int rm_write_audio(AVFormatContext *s, UINT8 *buf, int size)
  346. {
  347.     UINT8 buf1[size];
  348.     RMContext *rm = s->priv_data;
  349.     PutByteContext *pb = &s->pb;
  350.     StreamInfo *stream = rm->audio_stream;
  351.     int i;
  352.     write_packet_header(s, stream, size, stream->enc->key_frame);
  353.     
  354.     /* for AC3, the words seems to be reversed */
  355.     for(i=0;i<size;i+=2) {
  356.         buf1[i] = buf[i+1];
  357.         buf1[i+1] = buf[i];
  358.     }
  359.     put_buffer(pb, buf1, size);
  360.     put_flush_packet(pb);
  361.     stream->nb_frames++;
  362.     return 0;
  363. }
  364. static int rm_write_video(AVFormatContext *s, UINT8 *buf, int size)
  365. {
  366.     RMContext *rm = s->priv_data;
  367.     PutByteContext *pb = &s->pb;
  368.     StreamInfo *stream = rm->video_stream;
  369.     int key_frame = stream->enc->key_frame;
  370.     
  371.     /* XXX: this is incorrect: should be a parameter */
  372.     /* Well, I spent some time finding the meaning of these bits. I am
  373.        not sure I understood everything, but it works !! */
  374. #if 1
  375.     write_packet_header(s, stream, size + 7, key_frame);
  376.     /* bit 7: '1' if final packet of a frame converted in several packets */
  377.     put_byte(pb, 0x81); 
  378.     /* bit 7: '1' if I frame. bits 6..0 : sequence number in current
  379.        frame starting from 1 */
  380.     if (key_frame) {
  381.         put_byte(pb, 0x81); 
  382.     } else {
  383.         put_byte(pb, 0x01); 
  384.     }
  385.     put_short(pb, 0x4000 | (size)); /* total frame size */
  386.     put_short(pb, 0x4000 | (size));              /* offset from the start or the end */
  387. #else
  388.     /* seems to be used for prefetch/error correction. Help me ! */
  389.     write_packet_header(s, size + 6);
  390.     put_byte(pb, 0xc0); 
  391.     put_short(pb, 0x4000 | size); /* total frame size */
  392.     put_short(pb, 0x4000 + packet_number * 126);
  393. #endif
  394.     put_byte(pb, stream->nb_frames & 0xff); 
  395.     
  396.     put_buffer(pb, buf, size);
  397.     put_flush_packet(pb);
  398.     stream->nb_frames++;
  399.     return 0;
  400. }
  401. static int rm_write_trailer(AVFormatContext *s)
  402. {
  403.     RMContext *rm = s->priv_data;
  404.     int data_size, index_pos, i;
  405.     PutByteContext *pb = &s->pb;
  406.     if (!s->is_streamed) {
  407.         /* end of file: finish to write header */
  408.         index_pos = put_seek(pb, 0, SEEK_CUR);
  409.         data_size = index_pos - rm->data_pos;
  410.         /* index */
  411.         put_tag(pb, "INDX");
  412.         put_long(pb, 10 + 10 * rm->nb_streams);
  413.         put_short(pb, 0);
  414.         
  415.         for(i=0;i<rm->nb_streams;i++) {
  416.             put_long(pb, 0); /* zero indices */
  417.             put_short(pb, i); /* stream number */
  418.             put_long(pb, 0); /* next index */
  419.         }
  420.         /* undocumented end header */
  421.         put_long(pb, 0);
  422.         put_long(pb, 0);
  423.         
  424.         put_seek(pb, 0, SEEK_SET);
  425.         for(i=0;i<rm->nb_streams;i++)
  426.             rm->streams[i].total_frames = rm->streams[i].nb_frames;
  427.         rv10_write_header(s, data_size, index_pos);
  428.     } else {
  429.         /* undocumented end header */
  430.         put_long(pb, 0);
  431.         put_long(pb, 0);
  432.     }
  433.     put_flush_packet(pb);
  434.     free(rm);
  435.     return 0;
  436. }
  437. AVFormat rm_format = {
  438.     "rm",
  439.     "rm format",
  440.     "audio/x-pn-realaudio",
  441.     "rm,ra",
  442.     CODEC_ID_AC3,
  443.     CODEC_ID_RV10,
  444.     rm_write_header,
  445.     rm_write_audio,
  446.     rm_write_video,
  447.     rm_write_trailer,
  448. };
  449. AVFormat ra_format = {
  450.     "ra",
  451.     "ra format",
  452.     "audio/x-pn-realaudio",
  453.     "ra",
  454.     CODEC_ID_AC3,
  455.     CODEC_ID_NONE,
  456.     rm_write_header,
  457.     rm_write_audio,
  458.     NULL,
  459.     rm_write_trailer,
  460. };