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

流媒体/Mpeg4/MP4

开发平台:

Unix_Linux

  1. /*
  2.  * AVI 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. typedef long long offset_t;
  25. typedef struct AVIIndex {
  26.     unsigned char tag[4];
  27.     unsigned int flags, pos, len;
  28.     struct AVIIndex *next;
  29. } AVIIndex;
  30. typedef struct {
  31.     offset_t movi_list;
  32.     AVIIndex *first, *last;
  33. } AVIContext;
  34. static offset_t start_tag(PutByteContext *pb, char *tag)
  35. {
  36.     put_tag(pb, tag);
  37.     put_le32(pb, 0);
  38.     return put_pos(pb);
  39. }
  40. static void end_tag(PutByteContext *pb, offset_t start)
  41. {
  42.     offset_t pos;
  43.     pos = put_pos(pb);
  44.     put_seek(pb, start - 4, SEEK_SET);
  45.     put_le32(pb, pos - start);
  46.     put_seek(pb, pos, SEEK_SET);
  47. }
  48. #define AVIF_HASINDEX 0x00000010 // Index at end of file?
  49. #define AVIF_MUSTUSEINDEX 0x00000020
  50. #define AVIF_ISINTERLEAVED 0x00000100
  51. #define AVIF_TRUSTCKTYPE 0x00000800 // Use CKType to find key frames?
  52. #define AVIF_WASCAPTUREFILE 0x00010000
  53. #define AVIF_COPYRIGHTED 0x00020000
  54. #define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24))
  55. unsigned int codec_get_bmp_tag(int id)
  56. {
  57.     switch(id) {
  58.     case CODEC_ID_H263:
  59.         return MKTAG('I', '2', '6', '3'); 
  60.     case CODEC_ID_MJPEG:
  61.         return MKTAG('M', 'J', 'P', 'G'); 
  62.     case CODEC_ID_DIVX:
  63.         return MKTAG('d', 'i', 'v', 'x'); 
  64.     default:
  65.         abort();
  66.     }
  67. }
  68. /* BITMAPINFOHEADER header */
  69. void put_bmp_header(PutByteContext *pb, AVEncodeContext *enc)
  70. {
  71.     put_le32(pb, 40); /* size */
  72.     put_le32(pb, enc->width);
  73.     put_le32(pb, enc->height);
  74.     put_le16(pb, 1); /* planes */
  75.     put_le16(pb, 24); /* depth */
  76.     /* compression type */
  77.     put_le32(pb, codec_get_bmp_tag(enc->codec->id));
  78.     put_le32(pb, enc->width * enc->height * 3);
  79.     put_le32(pb, 0);
  80.     put_le32(pb, 0);
  81.     put_le32(pb, 0);
  82.     put_le32(pb, 0);
  83. }
  84. /* WAVEFORMATEX header */
  85. void put_wav_header(PutByteContext *pb, AVEncodeContext *enc)
  86. {
  87.     int id;
  88.     switch(enc->codec->id) {
  89.     case CODEC_ID_MP2:
  90.         id = 0x55; /* MP3 format */
  91.         break;
  92.     default:
  93.         abort();
  94.     }
  95.     put_le16(pb, id); 
  96.     put_le16(pb, enc->channels);
  97.     put_le32(pb, enc->rate);
  98.     put_le32(pb, enc->bit_rate / 8);
  99.     put_le16(pb, 1); /* block align */
  100.     put_le16(pb, 16); /* bits per sample */
  101.     put_le16(pb, 0); /* wav_extra_size */
  102. }
  103. static int avi_write_header(AVFormatContext *s)
  104. {
  105.     AVIContext *avi;
  106.     PutByteContext *pb = &s->pb;
  107.     int bitrate, n, i;
  108.     AVEncodeContext *stream;
  109.     offset_t list1, list2, strh, strf;
  110.     avi = malloc(sizeof(AVIContext));
  111.     if (!avi)
  112.         return -1;
  113.     memset(avi, 0, sizeof(AVIContext));
  114.     s->priv_data = avi;
  115.     put_tag(pb, "RIFF");
  116.     put_le32(pb, 0); /* file length */
  117.     put_tag(pb, "AVI ");
  118.     /* header list */
  119.     list1 = start_tag(pb, "LIST");
  120.     put_tag(pb, "hdrl");
  121.     /* avi header */
  122.     put_tag(pb, "avih");
  123.     put_le32(pb, 14 * 4);
  124.     bitrate = 0;
  125.     n = 0;
  126.     if (s->audio_enc) {
  127.         bitrate += s->audio_enc->bit_rate;
  128.         n++;
  129.     }
  130.     if (s->video_enc) {
  131.         bitrate += s->video_enc->bit_rate;
  132.         n++;
  133.     }
  134.     put_le32(pb, 1000000 / s->video_enc->rate);
  135.     put_le32(pb, bitrate / 8); /* XXX: not quite exact */
  136.     put_le32(pb, 0); /* padding */
  137.     put_le32(pb, AVIF_ISINTERLEAVED); /* flags */
  138.     put_le32(pb, 0); /* nb frames, filled later */
  139.     put_le32(pb, 0); /* initial frame */
  140.     put_le32(pb, n); /* nb streams */
  141.     put_le32(pb, 0); /* suggested buffer size */
  142.     put_le32(pb, s->video_enc->width);
  143.     put_le32(pb, s->video_enc->height);
  144.     put_le32(pb, 0); /* reserved */
  145.     put_le32(pb, 0); /* reserved */
  146.     put_le32(pb, 0); /* reserved */
  147.     put_le32(pb, 0); /* reserved */
  148.     
  149.     /* stream list */
  150.     for(i=0;i<n;i++) {
  151.         list2 = start_tag(pb, "LIST");
  152.         put_tag(pb, "strl");
  153.     
  154.         if (i == 0)
  155.             stream = s->video_enc;
  156.         else
  157.             stream = s->audio_enc;
  158.         /* stream generic header */
  159.         strh = start_tag(pb, "strh");
  160.         switch(stream->codec->type) {
  161.         case CODEC_TYPE_VIDEO:
  162.             put_tag(pb, "vids");
  163.             put_le32(pb, codec_get_bmp_tag(stream->codec->id));
  164.             put_le32(pb, 0); /* flags */
  165.             put_le16(pb, 0); /* priority */
  166.             put_le16(pb, 0); /* language */
  167.             put_le32(pb, 0); /* XXX: initial frame ? */
  168.             put_le32(pb, 1000); /* scale */
  169.             put_le32(pb, 1000 * stream->rate); /* rate */
  170.             put_le32(pb, 0); /* start */
  171.             put_le32(pb, 0); /* length, filled later */
  172.             put_le32(pb, 0); /* suggested buffer size */
  173.             put_le32(pb, 10000); /* quality */
  174.             put_le32(pb, stream->width * stream->height * 3); /* sample size */
  175.             break;
  176.         case CODEC_TYPE_AUDIO:
  177.             put_tag(pb, "auds");
  178.             put_le32(pb, 0);
  179.             put_le32(pb, 0); /* flags */
  180.             put_le16(pb, 0); /* priority */
  181.             put_le16(pb, 0); /* language */
  182.             put_le32(pb, 1); /* XXX: initial frame ? */
  183.             put_le32(pb, 1); /* scale */
  184.             put_le32(pb, stream->bit_rate / 8); /* rate */
  185.             put_le32(pb, 0); /* start */
  186.             put_le32(pb, 0); /* length, filled later */
  187.             put_le32(pb, 0); /* suggested buffer size */
  188.             put_le32(pb, -1); /* quality */
  189.             put_le32(pb, 1); /* sample size */
  190.             break;
  191.         }
  192.         put_le32(pb, 0);
  193.         put_le32(pb, 0);
  194.         end_tag(pb, strh);
  195.         strf = start_tag(pb, "strf");
  196.         switch(stream->codec->type) {
  197.         case CODEC_TYPE_VIDEO:
  198.             put_bmp_header(pb, stream);
  199.             break;
  200.         case CODEC_TYPE_AUDIO:
  201.             put_wav_header(pb, stream);
  202.             break;
  203.         }
  204.         end_tag(pb, strf);
  205.         end_tag(pb, list2);
  206.     }
  207.     end_tag(pb, list1);
  208.     avi->movi_list = start_tag(pb, "LIST");
  209.     avi->first = NULL;
  210.     avi->last = NULL;
  211.     put_tag(pb, "movi");
  212.     put_flush_packet(pb);
  213.     return 0;
  214. }
  215. static void new_index(AVFormatContext *s, AVEncodeContext *enc,
  216.                       UINT8 *buf, unsigned int size)
  217. {
  218.     AVIContext *avi = s->priv_data;
  219.     PutByteContext *pb = &s->pb;
  220.     AVIIndex *idx;
  221.     unsigned char tag[5];
  222.     unsigned int flags;
  223.     tag[0] = '0';
  224.     if (enc->codec->type == CODEC_TYPE_VIDEO) {
  225.         tag[1] = '0';
  226.         tag[2] = 'd';
  227.         tag[3] = 'c';
  228.         flags = enc->key_frame ? 0x10 : 0x00;
  229.     } else {
  230.         tag[1] = '1';
  231.         tag[2] = 'w';
  232.         tag[3] = 'b';
  233.         flags = 0;
  234.     }
  235.     if (!s->is_streamed) {
  236.         idx = malloc(sizeof(AVIIndex));
  237.         memcpy(idx->tag, tag, 4);
  238.         idx->flags = flags;
  239.         idx->pos = put_pos(pb) - avi->movi_list;
  240.         idx->len = size;
  241.         idx->next = NULL;
  242.         if (!avi->last)
  243.             avi->first = idx;
  244.         else
  245.             avi->last->next = idx;
  246.         avi->last = idx;
  247.     }
  248.     
  249.     put_buffer(pb, tag, 4);
  250.     put_le32(pb, size);
  251.     put_buffer(pb, buf, size);
  252.     if (size & 1)
  253.         put_byte(pb, 0);
  254.     put_flush_packet(pb);
  255. }
  256. static int avi_write_audio(AVFormatContext *s, UINT8 *buf, int size)
  257. {
  258.     new_index(s, s->audio_enc, buf, size);
  259.     return 0;
  260. }
  261. static int avi_write_video(AVFormatContext *s, UINT8 *buf, int size)
  262. {
  263.     new_index(s, s->video_enc, buf, size);
  264.     return 0;
  265. }
  266. static int avi_write_trailer(AVFormatContext *s)
  267. {
  268.     PutByteContext *pb = &s->pb;
  269.     AVIContext *avi = s->priv_data;
  270.     offset_t file_size, idx_chunk;
  271.     AVIIndex *idx;
  272.     if (!s->is_streamed) {
  273.         end_tag(pb, avi->movi_list);
  274.         idx_chunk = start_tag(pb, "idx1");
  275.         idx = avi->first;
  276.         while (idx != NULL) {
  277.             put_buffer(pb, idx->tag, 4);
  278.             put_le32(pb, idx->flags);
  279.             put_le32(pb, idx->pos);
  280.             put_le32(pb, idx->len);
  281.             idx = idx->next;
  282.         }
  283.         end_tag(pb, idx_chunk);
  284.         
  285.         /* update file size */
  286.         file_size = put_pos(pb);
  287.         put_seek(pb, 4, SEEK_SET);
  288.         put_le32(pb, file_size);
  289.         put_seek(pb, file_size, SEEK_SET);
  290.     }
  291.     put_flush_packet(pb);
  292.     free(avi);
  293.     return 0;
  294. }
  295. AVFormat avi_format = {
  296.     "avi",
  297.     "avi format",
  298.     "",
  299.     "avi",
  300.     CODEC_ID_MP2,
  301.     CODEC_ID_DIVX,
  302.     avi_write_header,
  303.     avi_write_audio,
  304.     avi_write_video,
  305.     avi_write_trailer,
  306. };