Commit 9aeeeb63 authored by Fabrice Bellard's avatar Fabrice Bellard

Initial revision


Originally committed as revision 2 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 77bb6835
This diff is collapsed.
CFLAGS= -O2 -Wall -g -I./libav
LDFLAGS= -g -L./libav
PROG= ffmpeg ffserver
all: lib $(PROG)
lib:
make -C libav all
ffmpeg: rmenc.o mpegmux.o asfenc.o jpegenc.o swfenc.o udp.o formats.o grab.o ffmpeg.o libav/libav.a
gcc $(LDFLAGS) -o $@ $^ -lav -lm
ffserver: rmenc.o mpegmux.o asfenc.o jpegenc.o swfenc.o formats.o grab.o ffserver.o libav/libav.a
gcc $(LDFLAGS) -o $@ $^ -lav -lpthread -lm
%.o: %.c
gcc $(CFLAGS) -c -o $@ $<
clean:
make -C libav clean
rm -f *.o *~ gmon.out TAGS $(PROG)
etags:
etags *.[ch] libav/*.[ch]
tar:
(cd .. ; tar zcvf ffmpeg-0.3.tgz ffmpeg --exclude CVS --exclude TAGS )
FFmpeg version 0.9 - (c) 2000 Gerard Lantau.
1) Introduction
---------------
ffmpeg is a hyper fast realtime audio/video encoder and streaming
server. It can grab from a standard Video4Linux video source and
convert it into several file formats based on DCT/motion compensation
encoding. Sound is compressed in MPEG audio layer 2 or using an AC3
compatible stream.
What makes ffmpeg interesting ?
- Innovative streaming technology : multiformat, real time encoding,
simple configuration.
- Simple and efficient video encoder: outputs MPEG1, H263 and Real
Video(tm) compatible bitstreams using the same encoder core.
- Real time encoding (25 fps in 352x288 on a K6 500) using the video4linux API.
- Generates I and P frames, which means it is far better than a MJPEG
encoder.
- Hyper fast MPEG audio layer 2 compression (50 times faster than
realtime on a K6 500).
- Hyper fast AC3 compatible encoder.
- simple and very small portable C source code, easy to understand and
to modify. It be may the smallest decent MPEG encoder :-)
ffmpeg is made of two programs:
* ffmpeg: soft VCR which encodes in real time to several formats.
* ffserver: live broadcast streaming server based on the ffmpeg core
encoders.
2) Documentation
----------------
read doc/ffmpeg.txt and doc/ffserver.txt to learn the basic features.
read ffmpeg
3) Licensing:
------------
* See the file COPYING. ffmpeg is licensed under the GNU General
Public License.
* Source code from third parties: The DCT code comes from the Berkeley
MPEG decoder and the JPEG encoder.
* This code should be patent free since it is very simple. I took care
to use the same video encoder core for all formats to show that they
really ARE THE SAME except for the encoding huffman codes.
Gerard Lantau (glantau@users.sourceforge.net).
This diff is collapsed.
- Sound is only handled in mono. The fixed psycho acoustic model is
very bad, although the quality is surpringly good for such a model !
- the bit rate control is really not correct.
- Only frame size multiple of 16 are handled.
- If you want a specific format to be added (I am thinking about
MJPEG, H261) please tell me. Of course, the format you choose should
be based on MPEG to be easily integrated
- ffmpeg can be used to generate streaming audio/video on a
server. Please tell me if you are interested.
Technical notes:
---------------
- To increase speed, only motion vectors (0,0) are tested
- The decision intra/predicted macroblock is the algorithm suggested
by the mpeg 1 specification.
- only Huffman based H263 is supported, mainly because of patent
issues.
- Many options can be modified only in the source code.
- I rewrote the mpeg audio layer 2 compatible encoder from scratch. It
is one of the simplest encoder you can imagine (800 lines of C code
!). It is also one of the fastest because of its simplicity. They
are still some problems of overflow. A minimal psycho acoustic model
could be added. Only mono stream can be generated. I may add stereo
if needed.
- I rewrote the AC3 audio encoder from scratch. It is fairly naive,
but the result are quiet interesting at 64 kbit/s. It includes
extensions for low sampling rates used in some Internet
formats. Differential and coupled stereo is not handled. Stereo
channels are simply handled as two mono channels.
ffmpeg TODO list:
- Add ASF format.
- add MJPEG codec.
- fix skip frame bug in mpeg video
- fix G2 audio problem (bad volume in AC3 ?)
- use non zero motion vectors.
- test fifo & master handling
- deny & allow + password.
- Improve psycho acoustic model for AC3 & mpeg audio.
- Improve the bit rate control for video codecs.
* ffmpeg can use YUV files as input :
ffmpeg /tmp/out.mpg /tmp/test
If will use the files:
/tmp/test0.Y, /tmp/test0.U, /tmp/test0.V,
/tmp/test1.Y, /tmp/test1.U, /tmp/test1.V, etc...
The Y files use twice the resolution of the U and V files. They are
raw files, without header. They can be generated by all decent video
decoders.
* ffmpeg can use a video4linux compatible video source :
ffmpeg /tmp/out.mpg
Note that you must activate the right video source and channel
before launching ffmpeg. You can use any TV viewer such as xawtv by
Gerd Knorr which I find very good.
* There are some importants options to know:
-s size set frame size [160x128]
-f format set encoding format [mpeg1]
-r fps set frame rate [25]
-b bitrate set the bitrate in kbit/s [100]
-t time set recording time in seconds [10.0]
The frame size can also be: cif, qcif, sqcif and 4cif.
The encoding format can be mpeg1, h263 or rv10.
Advanced options are:
-d device set video4linux device name
-g gop_size set the group of picture size.
An 'intra' frame is generated every gop_size frames.
-i use only intra images (speed up compression, but lower quality).
-c comment set the comment string.
Comment strings are only used for Real Video(tm) encoding. Tags are
used in the comment string. A typical comment string is:
"+title=Test Video +author=FFMpeg +copyright=Free +comment=Generated by FFMpeg 1.0"
The output file can be "-" to output to a pipe. This is only possible
with mpeg1 and h263 formats.
* Tips:
- For low bit rate application, use a low frame rate and a small gop
size. This is especially true for real video where the Linux player
does not seem to be very fast, so it can miss frames. An example is:
ffmpeg -g 3 -r 3 -t 10 -b 50 -s qcif -f rv10 /tmp/b.rm
- The parameter 'q' which is displayed while encoding is the current
quantizer. The value of 1 indicates that a very good quality could
be achieved. The value of 31 indicates the worst quality. If q=31
too often, it means that the encoder cannot compress enough to meet
your bit rate. You must either increase the bit rate, decrease the
frame rate or decrease the frame size.
# Port on which the server is listening. You must select a different
# port from your standard http web server if it is running on the same
# computer.
Port 8080
# Address on which the server is bound. Only useful if you have
# several network interfaces.
BindAddress 0.0.0.0
# Host and port of the master server if you which that this server
# duplicates another existing server. Otherwise, the server does the
# audio/video grab itself. See the following options for the grab parameters
#MasterServer http://localhost:80/index.html
# Grab parameters
#AudioDevice /dev/dsp
#VideoDevice /dev/video
# Number of simultaneous requests that can be handled. Since FFServer
# is very fast, this limit is determined mainly by your Internet
# connection speed.
MaxClients 1000
# Access Log file (uses standard Apache log file format)
# '-' is the standard output
CustomLog -
##################################################################
# Now you can define each stream which will be generated from the
# original audio and video stream. Each format has a filename (here
# 'test128.mpg'). FFServer will send this stream when answering a
# request containing this filename.
<Stream test1.mpg>
# Format of the stream : you can choose among:
# mpeg1 : MPEG1 multiplexed video and audio
# mpeg1video : only MPEG1 video
# mp2 : MPEG audio layer 2
# mp3 : MPEG audio layer 3 (currently sent as layer 2)
# rm : Real Networks compatible stream. Multiplexed audio and video.
# ra : Real Networks compatible stream. Audio only.
# mpjpeg : Multipart JPEG (works with Netscape without any plugin)
# jpeg : Generate a single JPEG image.
# asf : ASF compatible stream (Windows Media Player format)
# swf : Macromedia flash(tm) compatible stream
# master : special ffmpeg stream used to duplicate a server
Format mpeg1
# Bitrate for the audio stream. Codecs usually support only a few different bitrates.
AudioBitRate 32
# Number of audio channels : 1 = mono, 2 = stereo
AudioChannels 1
# Sampling frequency for audio. When using low bitrates, you should
# lower this frequency to 22050 or 11025. The supported frequencies
# depend on the selected audio codec.
AudioSampleRate 44100
# Bitrate for the video stream.
VideoBitRate 64
# Number of frames per second
VideoFrameRate 3
# Size of the video frame : WxH
# W : width, H : height
# The following abbreviation are defined : sqcif, qcif, cif, 4cif
#VideoSize 352x240
# transmit only intra frames (useful for low bitrates)
VideoIntraOnly
# If non intra only, an intra frame is transmitted every VideoGopSize
# frames Video synchronization can only begin at an I frames.
#VideoGopSize 12
</Stream>
# second mpeg stream with high frame rate
<Stream test2.mpg>
Format mpeg1video
VideoBitRate 128
VideoFrameRate 25
#VideoSize 352x240
VideoGopSize 25
</Stream>
##################################################################
# Another stream : used to download data to another server which
# duplicates this one
<Stream master>
Format master
</Stream>
##################################################################
# Another stream : Real with audio only at 32 kbits
<Stream test.ra>
Format ra
AudioBitRate 32
</Stream>
##################################################################
# Another stream : Real with audio and video at 64 kbits
<Stream test.rm>
Format rm
AudioBitRate 32
VideoBitRate 20
VideoFrameRate 2
VideoIntraOnly
</Stream>
##################################################################
# Another stream : Mpeg audio layer 2 at 64 kbits.
<Stream test.mp2>
Format mp2
AudioBitRate 64
AudioSampleRate 44100
</Stream>
<Stream test1.mp2>
Format mp2
AudioBitRate 32
AudioSampleRate 16000
</Stream>
##################################################################
# Another stream : Multipart JPEG
<Stream test.mjpg>
Format mpjpeg
VideoFrameRate 2
VideoIntraOnly
</Stream>
##################################################################
# Another stream : Multipart JPEG
<Stream test.jpg>
Format jpeg
# the parameters are choose here to take the same output as the
# Multipart JPEG one.
VideoFrameRate 2
VideoIntraOnly
</Stream>
##################################################################
# Another stream : Flash
<Stream test.swf>
Format swf
VideoFrameRate 2
VideoIntraOnly
</Stream>
##################################################################
# Another stream : ASF compatible
<Stream test.asf>
Format asf
AudioBitRate 64
AudioSampleRate 44100
VideoFrameRate 2
VideoIntraOnly
</Stream>
##################################################################
# Another stream : server status
<Stream stat.html>
Format status
</Stream>
This diff is collapsed.
This diff is collapsed.
#include <stdlib.h>
#include <stdio.h>
#include <netinet/in.h>
#include <linux/videodev.h>
#include <linux/soundcard.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <errno.h>
#include <sys/time.h>
#include <getopt.h>
#include <string.h>
#include "mpegenc.h"
AVFormat *first_format;
/* XXX: suppress it ! */
int data_out_size;
const char *comment_string =
"+title=Test Video +author=FFMpeg +copyright=Free +comment=Generated by FFMpeg 1.0";
void register_avformat(AVFormat *format)
{
AVFormat **p;
p = &first_format;
while (*p != NULL) p = &(*p)->next;
*p = format;
format->next = NULL;
}
AVFormat *guess_format(const char *short_name, const char *filename, const char *mime_type)
{
AVFormat *fmt, *fmt_found;
int score_max, score;
const char *ext, *p;
char ext1[32], *q;
/* find the proper file type */
fmt_found = NULL;
score_max = 0;
fmt = first_format;
while (fmt != NULL) {
score = 0;
if (fmt->name && short_name && !strcmp(fmt->name, short_name))
score += 100;
if (fmt->mime_type && mime_type && !strcmp(fmt->mime_type, mime_type))
score += 10;
if (filename && fmt->extensions) {
ext = strrchr(filename, '.');
if (ext) {
ext++;
p = fmt->extensions;
for(;;) {
q = ext1;
while (*p != '\0' && *p != ',')
*q++ = *p++;
*q = '\0';
if (!strcasecmp(ext1, ext)) {
score += 5;
break;
}
if (*p == '\0')
break;
p++;
}
}
}
if (score > score_max) {
score_max = score;
fmt_found = fmt;
}
fmt = fmt->next;
}
return fmt_found;
}
/* return TRUE if val is a prefix of str. If it returns TRUE, ptr is
set to the next character in 'str' after the prefix */
int strstart(const char *str, const char *val, const char **ptr)
{
const char *p, *q;
p = str;
q = val;
while (*q != '\0') {
if (*p != *q)
return 0;
p++;
q++;
}
if (ptr)
*ptr = p;
return 1;
}
/* simple formats */
int raw_write_header(struct AVFormatContext *s)
{
return 0;
}
int raw_write_audio(struct AVFormatContext *s,
unsigned char *buf, int size)
{
put_buffer(&s->pb, buf, size);
put_flush_packet(&s->pb);
return 0;
}
int raw_write_video(struct AVFormatContext *s,
unsigned char *buf, int size)
{
put_buffer(&s->pb, buf, size);
put_flush_packet(&s->pb);
return 0;
}
int raw_write_trailer(struct AVFormatContext *s)
{
return 0;
}
AVFormat mp2_format = {
"mp2",
"MPEG audio layer 2",
"audio/x-mpeg",
"mp2,mp3",
CODEC_ID_MP2,
0,
raw_write_header,
raw_write_audio,
NULL,
raw_write_trailer,
};
AVFormat ac3_format = {
"ac3",
"raw ac3",
"audio/x-ac3",
"ac3",
CODEC_ID_AC3,
0,
raw_write_header,
raw_write_audio,
NULL,
raw_write_trailer,
};
AVFormat h263_format = {
"h263",
"raw h263",
"video/x-h263",
"h263",
0,
CODEC_ID_H263,
raw_write_header,
NULL,
raw_write_video,
raw_write_trailer,
};
AVFormat mpeg1video_format = {
"mpeg1video",
"MPEG1 video",
"video/mpeg",
"mpg,mpeg",
0,
CODEC_ID_MPEG1VIDEO,
raw_write_header,
NULL,
raw_write_video,
raw_write_trailer,
};
/* encoder management */
AVEncoder *first_encoder;
void register_avencoder(AVEncoder *format)
{
AVEncoder **p;
p = &first_encoder;
while (*p != NULL) p = &(*p)->next;
*p = format;
format->next = NULL;
}
int avencoder_open(AVEncodeContext *avctx, AVEncoder *codec)
{
int ret;
avctx->codec = codec;
avctx->frame_number = 0;
avctx->priv_data = malloc(codec->priv_data_size);
if (!avctx->priv_data)
return -ENOMEM;
memset(avctx->priv_data, 0, codec->priv_data_size);
ret = avctx->codec->init(avctx);
if (ret < 0) {
free(avctx->priv_data);
avctx->priv_data = NULL;
return ret;
}
return 0;
}
int avencoder_encode(AVEncodeContext *avctx, UINT8 *buf, int buf_size, void *data)
{
int ret;
ret = avctx->codec->encode(avctx, buf, buf_size, data);
avctx->frame_number++;
return ret;
}
int avencoder_close(AVEncodeContext *avctx)
{
if (avctx->codec->close)
avctx->codec->close(avctx);
free(avctx->priv_data);
avctx->priv_data = NULL;
return 0;
}
AVEncoder *avencoder_find(enum CodecID id)
{
AVEncoder *p;
p = first_encoder;
while (p) {
if (p->id == id)
return p;
p = p->next;
}
return NULL;
}
void avencoder_string(char *buf, int buf_size, AVEncodeContext *enc)
{
switch(enc->codec->type) {
case CODEC_TYPE_VIDEO:
snprintf(buf, buf_size,
"Video: %s, %dx%d, %d fps, %d kb/s",
enc->codec->name, enc->width, enc->height, enc->rate, enc->bit_rate / 1000);
break;
case CODEC_TYPE_AUDIO:
snprintf(buf, buf_size,
"Audio: %s, %d Hz, %s, %d kb/s",
enc->codec->name, enc->rate,
enc->channels == 2 ? "stereo" : "mono",
enc->bit_rate / 1000);
break;
default:
abort();
}
}
/* PutByteFormat */
int init_put_byte(PutByteContext *s,
unsigned char *buffer,
int buffer_size,
void *opaque,
void (*write_packet)(void *opaque, UINT8 *buf, int buf_size),
int (*write_seek)(void *opaque, long long offset, int whence))
{
s->buffer = buffer;
s->buf_ptr = buffer;
s->buf_end = buffer + buffer_size;
s->opaque = opaque;
s->write_packet = write_packet;
s->write_seek = write_seek;
s->pos = 0;
return 0;
}
static void flush_buffer(PutByteContext *s)
{
if (s->buf_ptr > s->buffer) {
if (s->write_packet)
s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer);
s->pos += s->buf_ptr - s->buffer;
}
s->buf_ptr = s->buffer;
}
void put_byte(PutByteContext *s, int b)
{
*(s->buf_ptr)++ = b;
if (s->buf_ptr >= s->buf_end)
flush_buffer(s);
}
void put_buffer(PutByteContext *s, unsigned char *buf, int size)
{
int len;
while (size > 0) {
len = (s->buf_end - s->buf_ptr);
if (len > size)
len = size;
memcpy(s->buf_ptr, buf, len);
s->buf_ptr += len;
if (s->buf_ptr >= s->buf_end)
flush_buffer(s);
buf += len;
size -= len;
}
}
void put_flush_packet(PutByteContext *s)
{
flush_buffer(s);
}
/* XXX: this seek is not correct if we go after the end of the written data */
long long put_seek(PutByteContext *s, long long offset, int whence)
{
long long offset1;
if (whence != SEEK_CUR && whence != SEEK_SET)
return -1;
if (whence == SEEK_CUR)
offset += s->pos + s->buf_ptr - s->buffer;
offset1 = offset - s->pos;
if (offset1 >= 0 && offset1 < (s->buf_end - s->buffer)) {
/* can do the seek inside the buffer */
s->buf_ptr = s->buffer + offset1;
} else {
if (!s->write_seek)
return -1;
flush_buffer(s);
s->write_seek(s->opaque, offset, whence);
}
return offset;
}
long long put_pos(PutByteContext *s)
{
return put_seek(s, 0, SEEK_CUR);
}
void put_le32(PutByteContext *s, unsigned int val)
{
put_byte(s, val);
put_byte(s, val >> 8);
put_byte(s, val >> 16);
put_byte(s, val >> 24);
}
void put_le64(PutByteContext *s, unsigned long long val)
{
put_le32(s, val & 0xffffffff);
put_le32(s, val >> 32);
}
void put_le16(PutByteContext *s, unsigned int val)
{
put_byte(s, val);
put_byte(s, val >> 8);
}
void put_tag(PutByteContext *s, char *tag)
{
while (*tag) {
put_byte(s, *tag++);
}
}
/*
* Linux audio/video grab interface
* Copyright (c) 2000 Gerard Lantau.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include <netinet/in.h>
#include <linux/videodev.h>
#include <linux/soundcard.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <errno.h>
#include <sys/time.h>
#include <getopt.h>
#include "mpegenc.h"
#include "mpegvideo.h"
long long gettime(void)
{
struct timeval tv;
gettimeofday(&tv,NULL);
return (long long)tv.tv_sec * 1000000 + tv.tv_usec;
}
/* v4l capture */
const char *v4l_device = "/dev/video";
static struct video_capability video_cap;
int video_fd = -1;
UINT8 *video_buf, *picture_buf;
struct video_mbuf gb_buffers;
struct video_mmap gb_buf;
struct video_audio audio;
int gb_frame = 0;
long long time_frame;
int frame_rate;
int use_mmap = 0;
int v4l_init(int rate, int width, int height)
{
frame_rate = rate;
video_fd = open(v4l_device, O_RDWR);
if (ioctl(video_fd,VIDIOCGCAP,&video_cap) < 0) {
perror("VIDIOCGCAP");
return -1;
}
/* unmute audio */
ioctl(video_fd, VIDIOCGAUDIO, &audio);
audio.flags &= ~VIDEO_AUDIO_MUTE;
ioctl(video_fd, VIDIOCSAUDIO, &audio);
if (!(video_cap.type & VID_TYPE_CAPTURE)) {
/* try to use read based access */
struct video_window win;
int val;
win.x = 0;
win.y = 0;
win.width = width;
win.height = height;
win.chromakey = -1;
win.flags = 0;
ioctl(video_fd, VIDIOCSWIN, &win);
val = 1;
ioctl(video_fd, VIDIOCCAPTURE, &val);
video_buf = malloc( width * height * 2);
picture_buf = malloc( (width * height * 3) / 2);
use_mmap = 0;
return 0;
}
if (ioctl(video_fd,VIDIOCGMBUF,&gb_buffers) < 0) {
perror("ioctl VIDIOCGMBUF");
}
video_buf = mmap(0,gb_buffers.size,PROT_READ|PROT_WRITE,MAP_SHARED,video_fd,0);
if ((unsigned char*)-1 == video_buf) {
perror("mmap");
return -1;
}
gb_frame = 0;
time_frame = gettime();
/* start to grab the first frame */
gb_buf.frame = 1 - gb_frame;
gb_buf.height = height;
gb_buf.width = width;
gb_buf.format = VIDEO_PALETTE_YUV420P;
if (ioctl(video_fd, VIDIOCMCAPTURE, &gb_buf) < 0) {
if (errno == EAGAIN)
fprintf(stderr,"Cannot Sync\n");
else
perror("VIDIOCMCAPTURE");
return -1;
}
use_mmap = 1;
return 0;
}
/* test with read call and YUV422 stream */
static int v4l_basic_read_picture(UINT8 *picture[3],
int width, int height,
int picture_number)
{
int x, y;
UINT8 *p, *lum, *cb, *cr;
if (read(video_fd, video_buf, width * height * 2) < 0)
perror("read");
picture[0] = picture_buf;
picture[1] = picture_buf + width * height;
picture[2] = picture_buf + (width * height) + (width * height) / 4;
/* XXX: optimize */
lum = picture[0];
cb = picture[1];
cr = picture[2];
p = video_buf;
for(y=0;y<height;y+=2) {
for(x=0;x<width;x+=2) {
lum[0] = p[0];
cb[0] = p[1];
lum[1] = p[2];
cr[0] = p[3];
p += 4;
lum += 2;
cb++;
cr++;
}
for(x=0;x<width;x+=2) {
lum[0] = p[0];
lum[1] = p[2];
p += 4;
lum += 2;
}
}
return 0;
}
static int v4l_mm_read_picture(UINT8 *picture[3],
int width, int height,
int picture_number)
{
UINT8 *ptr;
int size;
long long curtime;
/* wait based on the frame rate */
time_frame += 1000000 / frame_rate;
do {
curtime = gettime();
} while (curtime < time_frame);
gb_buf.frame = gb_frame;
if (ioctl(video_fd, VIDIOCMCAPTURE, &gb_buf) < 0) {
if (errno == EAGAIN)
fprintf(stderr,"Cannot Sync\n");
else
perror("VIDIOCMCAPTURE");
return -1;
}
gb_frame = 1 - gb_frame;
if (ioctl(video_fd, VIDIOCSYNC, &gb_frame) < 0) {
if (errno != EAGAIN) {
perror("VIDIOCSYNC");
}
}
size = width * height;
ptr = video_buf + gb_buffers.offsets[gb_frame];
picture[0] = ptr;
picture[1] = ptr + size;
picture[2] = ptr + size + (size / 4);
return 0;
}
int v4l_read_picture(UINT8 *picture[3],
int width, int height,
int picture_number)
{
if (use_mmap) {
return v4l_mm_read_picture(picture, width, height, picture_number);
} else {
return v4l_basic_read_picture(picture, width, height, picture_number);
}
}
/* open audio device */
int audio_open(int freq, int channels)
{
int audio_fd, tmp, err;
audio_fd = open("/dev/dsp",O_RDONLY);
if (audio_fd == -1) {
perror("/dev/dsp");
return -1;
}
/* non blocking mode */
fcntl(audio_fd, F_SETFL, O_NONBLOCK);
#if 0
tmp=(NB_FRAGMENTS << 16) | FRAGMENT_BITS;
err=ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &tmp);
if (err < 0) {
perror("SNDCTL_DSP_SETFRAGMENT");
}
#endif
/* always set to this size */
/* XXX: incorrect if big endian */
tmp=AFMT_S16_LE;
err=ioctl(audio_fd,SNDCTL_DSP_SETFMT,&tmp);
if (err < 0) {
perror("SNDCTL_DSP_SETFMT");
}
tmp= (channels == 2);
err=ioctl(audio_fd,SNDCTL_DSP_STEREO,&tmp);
if (err < 0) {
perror("SNDCTL_DSP_STEREO");
}
/* should be last */
tmp = freq;
err=ioctl(audio_fd, SNDCTL_DSP_SPEED, &tmp);
if (err < 0) {
perror("SNDCTL_DSP_SPEED");
}
return audio_fd;
}
/*
* Miscellaneous MJPEG based formats
* Copyright (c) 2000 Gerard Lantau.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include <netinet/in.h>
#include <string.h>
#include "mpegenc.h"
/* Multipart JPEG */
#define BOUNDARY_TAG "ffserver"
static int mpjpeg_write_header(AVFormatContext *s)
{
UINT8 buf1[256];
snprintf(buf1, sizeof(buf1), "--%s\n", BOUNDARY_TAG);
put_buffer(&s->pb, buf1, strlen(buf1));
put_flush_packet(&s->pb);
return 0;
}
static int mpjpeg_write_video(AVFormatContext *s, UINT8 *buf, int size)
{
UINT8 buf1[256];
snprintf(buf1, sizeof(buf1), "Content-type: image/jpeg\n\n");
put_buffer(&s->pb, buf1, strlen(buf1));
put_buffer(&s->pb, buf, size);
snprintf(buf1, sizeof(buf1), "\n--%s\n", BOUNDARY_TAG);
put_buffer(&s->pb, buf1, strlen(buf1));
put_flush_packet(&s->pb);
return 0;
}
static int mpjpeg_write_trailer(AVFormatContext *s)
{
return 0;
}
AVFormat mpjpeg_format = {
"mpjpeg",
"Mime multipart JPEG format",
"multipart/x-mixed-replace;boundary=" BOUNDARY_TAG,
"mjpg",
CODEC_ID_NONE,
CODEC_ID_MJPEG,
mpjpeg_write_header,
NULL,
mpjpeg_write_video,
mpjpeg_write_trailer,
};
/* single frame JPEG */
static int jpeg_write_header(AVFormatContext *s)
{
return 0;
}
static int jpeg_write_video(AVFormatContext *s, UINT8 *buf, int size)
{
put_buffer(&s->pb, buf, size);
put_flush_packet(&s->pb);
return 1; /* no more data can be sent */
}
static int jpeg_write_trailer(AVFormatContext *s)
{
return 0;
}
AVFormat jpeg_format = {
"jpeg",
"JPEG image",
"image/jpeg",
"jpg,jpeg",
CODEC_ID_NONE,
CODEC_ID_MJPEG,
jpeg_write_header,
NULL,
jpeg_write_video,
jpeg_write_trailer,
};
CFLAGS= -O2 -Wall -g
LDFLAGS= -g
OBJS= common.o mpegvideo.o h263enc.o jrevdct.o jfdctfst.o \
mpegaudio.o ac3enc.o mjpegenc.o resample.o
LIB= libav.a
all: $(LIB)
$(LIB): $(OBJS)
ar rcs $@ $(OBJS)
%.o: %.c
gcc $(CFLAGS) -c -o $@ $<
clean:
rm -f *.o *~ *.a
This diff is collapsed.
#define AC3_FRAME_SIZE (6*256)
#define AC3_MAX_CODED_FRAME_SIZE 3840 /* in bytes */
#define AC3_MAX_CHANNELS 2 /* we handle at most two channels, although
AC3 allows 6 channels */
typedef struct AC3EncodeContext {
PutBitContext pb;
int nb_channels;
int bit_rate;
int sample_rate;
int bsid;
int frame_size_min; /* minimum frame size in case rounding is necessary */
int frame_size; /* current frame size in words */
int halfratecod;
int frmsizecod;
int fscod; /* frequency */
int acmod;
int bsmod;
short last_samples[AC3_MAX_CHANNELS][256];
int chbwcod[AC3_MAX_CHANNELS];
int nb_coefs[AC3_MAX_CHANNELS];
/* bitrate allocation control */
int sgaincod, sdecaycod, fdecaycod, dbkneecod, floorcod;
int sgain, sdecay, fdecay, dbknee, floor;
int csnroffst;
int fgaincod[AC3_MAX_CHANNELS];
int fsnroffst[AC3_MAX_CHANNELS];
/* mantissa encoding */
int mant1_cnt, mant2_cnt, mant4_cnt;
} AC3EncodeContext;
/* tables taken directly from AC3 spec */
/* possible bitrates */
static const UINT16 bitratetab[19] = {
32, 40, 48, 56, 64, 80, 96, 112, 128,
160, 192, 224, 256, 320, 384, 448, 512, 576, 640
};
/* AC3 MDCT window */
/* MDCT window */
static const INT16 ac3_window[256]= {
4, 7, 12, 16, 21, 28, 34, 42,
51, 61, 72, 84, 97, 111, 127, 145,
164, 184, 207, 231, 257, 285, 315, 347,
382, 419, 458, 500, 544, 591, 641, 694,
750, 810, 872, 937, 1007, 1079, 1155, 1235,
1318, 1406, 1497, 1593, 1692, 1796, 1903, 2016,
2132, 2253, 2379, 2509, 2644, 2783, 2927, 3076,
3230, 3389, 3552, 3721, 3894, 4072, 4255, 4444,
4637, 4835, 5038, 5246, 5459, 5677, 5899, 6127,
6359, 6596, 6837, 7083, 7334, 7589, 7848, 8112,
8380, 8652, 8927, 9207, 9491, 9778,10069,10363,
10660,10960,11264,11570,11879,12190,12504,12820,
13138,13458,13780,14103,14427,14753,15079,15407,
15735,16063,16392,16720,17049,17377,17705,18032,
18358,18683,19007,19330,19651,19970,20287,20602,
20914,21225,21532,21837,22139,22438,22733,23025,
23314,23599,23880,24157,24430,24699,24964,25225,
25481,25732,25979,26221,26459,26691,26919,27142,
27359,27572,27780,27983,28180,28373,28560,28742,
28919,29091,29258,29420,29577,29729,29876,30018,
30155,30288,30415,30538,30657,30771,30880,30985,
31086,31182,31274,31363,31447,31528,31605,31678,
31747,31814,31877,31936,31993,32046,32097,32145,
32190,32232,32272,32310,32345,32378,32409,32438,
32465,32490,32513,32535,32556,32574,32592,32608,
32623,32636,32649,32661,32671,32681,32690,32698,
32705,32712,32718,32724,32729,32733,32737,32741,
32744,32747,32750,32752,32754,32756,32757,32759,
32760,32761,32762,32763,32764,32764,32765,32765,
32766,32766,32766,32766,32767,32767,32767,32767,
32767,32767,32767,32767,32767,32767,32767,32767,
32767,32767,32767,32767,32767,32767,32767,32767,
};
static UINT8 masktab[253];
static const UINT8 latab[260]= {
0x0040,0x003f,0x003e,0x003d,0x003c,0x003b,0x003a,0x0039,0x0038,0x0037,
0x0036,0x0035,0x0034,0x0034,0x0033,0x0032,0x0031,0x0030,0x002f,0x002f,
0x002e,0x002d,0x002c,0x002c,0x002b,0x002a,0x0029,0x0029,0x0028,0x0027,
0x0026,0x0026,0x0025,0x0024,0x0024,0x0023,0x0023,0x0022,0x0021,0x0021,
0x0020,0x0020,0x001f,0x001e,0x001e,0x001d,0x001d,0x001c,0x001c,0x001b,
0x001b,0x001a,0x001a,0x0019,0x0019,0x0018,0x0018,0x0017,0x0017,0x0016,
0x0016,0x0015,0x0015,0x0015,0x0014,0x0014,0x0013,0x0013,0x0013,0x0012,
0x0012,0x0012,0x0011,0x0011,0x0011,0x0010,0x0010,0x0010,0x000f,0x000f,
0x000f,0x000e,0x000e,0x000e,0x000d,0x000d,0x000d,0x000d,0x000c,0x000c,
0x000c,0x000c,0x000b,0x000b,0x000b,0x000b,0x000a,0x000a,0x000a,0x000a,
0x000a,0x0009,0x0009,0x0009,0x0009,0x0009,0x0008,0x0008,0x0008,0x0008,
0x0008,0x0008,0x0007,0x0007,0x0007,0x0007,0x0007,0x0007,0x0006,0x0006,
0x0006,0x0006,0x0006,0x0006,0x0006,0x0006,0x0005,0x0005,0x0005,0x0005,
0x0005,0x0005,0x0005,0x0005,0x0004,0x0004,0x0004,0x0004,0x0004,0x0004,
0x0004,0x0004,0x0004,0x0004,0x0004,0x0003,0x0003,0x0003,0x0003,0x0003,
0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0003,0x0002,
0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,
0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,0x0001,0x0001,
0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,
0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,
0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
};
static const UINT16 hth[50][3]= {
{ 0x04d0,0x04f0,0x0580 },
{ 0x04d0,0x04f0,0x0580 },
{ 0x0440,0x0460,0x04b0 },
{ 0x0400,0x0410,0x0450 },
{ 0x03e0,0x03e0,0x0420 },
{ 0x03c0,0x03d0,0x03f0 },
{ 0x03b0,0x03c0,0x03e0 },
{ 0x03b0,0x03b0,0x03d0 },
{ 0x03a0,0x03b0,0x03c0 },
{ 0x03a0,0x03a0,0x03b0 },
{ 0x03a0,0x03a0,0x03b0 },
{ 0x03a0,0x03a0,0x03b0 },
{ 0x03a0,0x03a0,0x03a0 },
{ 0x0390,0x03a0,0x03a0 },
{ 0x0390,0x0390,0x03a0 },
{ 0x0390,0x0390,0x03a0 },
{ 0x0380,0x0390,0x03a0 },
{ 0x0380,0x0380,0x03a0 },
{ 0x0370,0x0380,0x03a0 },
{ 0x0370,0x0380,0x03a0 },
{ 0x0360,0x0370,0x0390 },
{ 0x0360,0x0370,0x0390 },
{ 0x0350,0x0360,0x0390 },
{ 0x0350,0x0360,0x0390 },
{ 0x0340,0x0350,0x0380 },
{ 0x0340,0x0350,0x0380 },
{ 0x0330,0x0340,0x0380 },
{ 0x0320,0x0340,0x0370 },
{ 0x0310,0x0320,0x0360 },
{ 0x0300,0x0310,0x0350 },
{ 0x02f0,0x0300,0x0340 },
{ 0x02f0,0x02f0,0x0330 },
{ 0x02f0,0x02f0,0x0320 },
{ 0x02f0,0x02f0,0x0310 },
{ 0x0300,0x02f0,0x0300 },
{ 0x0310,0x0300,0x02f0 },
{ 0x0340,0x0320,0x02f0 },
{ 0x0390,0x0350,0x02f0 },
{ 0x03e0,0x0390,0x0300 },
{ 0x0420,0x03e0,0x0310 },
{ 0x0460,0x0420,0x0330 },
{ 0x0490,0x0450,0x0350 },
{ 0x04a0,0x04a0,0x03c0 },
{ 0x0460,0x0490,0x0410 },
{ 0x0440,0x0460,0x0470 },
{ 0x0440,0x0440,0x04a0 },
{ 0x0520,0x0480,0x0460 },
{ 0x0800,0x0630,0x0440 },
{ 0x0840,0x0840,0x0450 },
{ 0x0840,0x0840,0x04e0 },
};
static const UINT8 baptab[64]= {
0, 1, 1, 1, 1, 1, 2, 2, 3, 3,
3, 4, 4, 5, 5, 6, 6, 6, 6, 7,
7, 7, 7, 8, 8, 8, 8, 9, 9, 9,
9, 10, 10, 10, 10, 11, 11, 11, 11, 12,
12, 12, 12, 13, 13, 13, 13, 14, 14, 14,
14, 14, 14, 14, 14, 15, 15, 15, 15, 15,
15, 15, 15, 15,
};
static const UINT8 sdecaytab[4]={
0x0f, 0x11, 0x13, 0x15,
};
static const UINT8 fdecaytab[4]={
0x3f, 0x53, 0x67, 0x7b,
};
static const UINT16 sgaintab[4]= {
0x540, 0x4d8, 0x478, 0x410,
};
static const UINT16 dbkneetab[4]= {
0x000, 0x700, 0x900, 0xb00,
};
static const UINT16 floortab[8]= {
0x2f0, 0x2b0, 0x270, 0x230, 0x1f0, 0x170, 0x0f0, 0xf800,
};
static const UINT16 fgaintab[8]= {
0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380, 0x400,
};
static const UINT8 bndsz[50]={
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3,
3, 6, 6, 6, 6, 6, 6, 12, 12, 12, 12, 24, 24, 24, 24, 24
};
static UINT8 bndtab[51];
/* fft & mdct sin cos tables */
static INT16 costab[64];
static INT16 sintab[64];
static INT16 fft_rev[512];
static INT16 xcos1[128];
static INT16 xsin1[128];
static UINT16 crc_table[256];
#include "common.h"
enum CodecID {
CODEC_ID_NONE,
CODEC_ID_MPEG1VIDEO,
CODEC_ID_H263,
CODEC_ID_RV10,
CODEC_ID_MP2,
CODEC_ID_AC3,
CODEC_ID_MJPEG,
};
enum CodecType {
CODEC_TYPE_VIDEO,
CODEC_TYPE_AUDIO,
};
typedef struct AVEncodeContext {
int bit_rate;
int rate; /* frames per sec or samples per sec */
/* video only */
int width, height;
int gop_size; /* 0 = intra only */
/* audio only */
int channels;
/* the following data should not be initialized */
int frame_size; /* in samples, initialized when calling 'init' */
int frame_number; /* audio or video frame number */
int key_frame; /* true if the previous compressed frame was
a key frame (intra, or seekable) */
struct AVEncoder *codec;
void *priv_data;
} AVEncodeContext;
typedef struct AVEncoder {
char *name;
int type;
int id;
int priv_data_size;
int (*init)(AVEncodeContext *);
int (*encode)(AVEncodeContext *, UINT8 *buf, int buf_size, void *data);
int (*close)(AVEncodeContext *);
struct AVEncoder *next;
} AVEncoder;
extern AVEncoder ac3_encoder;
extern AVEncoder mp2_encoder;
extern AVEncoder mpeg1video_encoder;
extern AVEncoder h263_encoder;
extern AVEncoder rv10_encoder;
extern AVEncoder mjpeg_encoder;
/* resample.c */
typedef struct {
/* fractional resampling */
UINT32 incr; /* fractional increment */
UINT32 frac;
int last_sample;
/* integer down sample */
int iratio; /* integer divison ratio */
int icount, isum;
int inv;
} ReSampleChannelContext;
typedef struct {
ReSampleChannelContext channel_ctx[2];
float ratio;
/* channel convert */
int input_channels, output_channels;
} ReSampleContext;
int audio_resample_init(ReSampleContext *s,
int output_channels, int input_channels,
int output_rate, int input_rate);
int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples);
/*
* Common bit/dsp utils
* Copyright (c) 2000 Gerard Lantau.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <math.h>
#include "common.h"
#define NDEBUG
#include <assert.h>
void init_put_bits(PutBitContext *s,
UINT8 *buffer, int buffer_size,
void *opaque,
void (*write_data)(void *, UINT8 *, int))
{
s->buf = buffer;
s->buf_ptr = s->buf;
s->buf_end = s->buf + buffer_size;
s->bit_cnt=0;
s->bit_buf=0;
s->data_out_size = 0;
s->write_data = write_data;
s->opaque = opaque;
}
static void flush_buffer(PutBitContext *s)
{
int size;
if (s->write_data) {
size = s->buf_ptr - s->buf;
if (size > 0)
s->write_data(s->opaque, s->buf, size);
s->buf_ptr = s->buf;
s->data_out_size += size;
}
}
void put_bits(PutBitContext *s, int n, unsigned int value)
{
unsigned int bit_buf;
int bit_cnt;
assert(n == 32 || value < (1U << n));
bit_buf = s->bit_buf;
bit_cnt = s->bit_cnt;
// printf("n=%d value=%x cnt=%d buf=%x\n", n, value, bit_cnt, bit_buf);
/* XXX: optimize */
if (n < (32-bit_cnt)) {
bit_buf |= value << (32 - n - bit_cnt);
bit_cnt+=n;
} else {
bit_buf |= value >> (n + bit_cnt - 32);
*(UINT32 *)s->buf_ptr = htonl(bit_buf);
//printf("bitbuf = %08x\n", bit_buf);
s->buf_ptr+=4;
if (s->buf_ptr >= s->buf_end)
flush_buffer(s);
bit_cnt=bit_cnt + n - 32;
if (bit_cnt == 0) {
bit_buf = 0;
} else {
bit_buf = value << (32 - bit_cnt);
}
}
s->bit_buf = bit_buf;
s->bit_cnt = bit_cnt;
}
/* return the number of bits output */
long long get_bit_count(PutBitContext *s)
{
return (s->buf_ptr - s->buf + s->data_out_size) * 8 + (long long)s->bit_cnt;
}
void align_put_bits(PutBitContext *s)
{
put_bits(s,(8 - s->bit_cnt) & 7,0);
}
/* pad the end of the output stream with zeros */
void flush_put_bits(PutBitContext *s)
{
while (s->bit_cnt > 0) {
/* XXX: should test end of buffer */
*s->buf_ptr++=s->bit_buf >> 24;
s->bit_buf<<=8;
s->bit_cnt-=8;
}
flush_buffer(s);
s->bit_cnt=0;
s->bit_buf=0;
}
/* for jpeg : espace 0xff with 0x00 after it */
void jput_bits(PutBitContext *s, int n, unsigned int value)
{
unsigned int bit_buf, b;
int bit_cnt, i;
assert(n == 32 || value < (1U << n));
bit_buf = s->bit_buf;
bit_cnt = s->bit_cnt;
//printf("n=%d value=%x cnt=%d buf=%x\n", n, value, bit_cnt, bit_buf);
/* XXX: optimize */
if (n < (32-bit_cnt)) {
bit_buf |= value << (32 - n - bit_cnt);
bit_cnt+=n;
} else {
bit_buf |= value >> (n + bit_cnt - 32);
/* handle escape */
for(i=0;i<4;i++) {
b = (bit_buf >> 24);
*(s->buf_ptr++) = b;
if (b == 0xff)
*(s->buf_ptr++) = 0;
bit_buf <<= 8;
}
/* we flush the buffer sooner to handle worst case */
if (s->buf_ptr >= (s->buf_end - 8))
flush_buffer(s);
bit_cnt=bit_cnt + n - 32;
if (bit_cnt == 0) {
bit_buf = 0;
} else {
bit_buf = value << (32 - bit_cnt);
}
}
s->bit_buf = bit_buf;
s->bit_cnt = bit_cnt;
}
/* pad the end of the output stream with zeros */
void jflush_put_bits(PutBitContext *s)
{
unsigned int b;
while (s->bit_cnt > 0) {
b = s->bit_buf >> 24;
*s->buf_ptr++ = b;
if (b == 0xff)
*s->buf_ptr++ = 0;
s->bit_buf<<=8;
s->bit_cnt-=8;
}
flush_buffer(s);
s->bit_cnt=0;
s->bit_buf=0;
}
#ifndef COMMON_H
#define COMMON_H
typedef unsigned char UINT8;
typedef unsigned short UINT16;
typedef unsigned int UINT32;
typedef signed char INT8;
typedef signed short INT16;
typedef signed int INT32;
/* bit I/O */
struct PutBitContext;
typedef void (*WriteDataFunc)(void *, UINT8 *, int);
typedef struct PutBitContext {
UINT8 *buf, *buf_ptr, *buf_end;
int bit_cnt;
UINT32 bit_buf;
long long data_out_size; /* in bytes */
void *opaque;
WriteDataFunc write_data;
} PutBitContext;
void init_put_bits(PutBitContext *s,
UINT8 *buffer, int buffer_size,
void *opaque,
void (*write_data)(void *, UINT8 *, int));
void put_bits(PutBitContext *s, int n, unsigned int value);
long long get_bit_count(PutBitContext *s);
void align_put_bits(PutBitContext *s);
void flush_put_bits(PutBitContext *s);
/* jpeg specific put_bits */
void jput_bits(PutBitContext *s, int n, unsigned int value);
void jflush_put_bits(PutBitContext *s);
/* misc math functions */
extern inline int log2(unsigned int v)
{
int n;
n = 0;
if (v & 0xffff0000) {
v >>= 16;
n += 16;
}
if (v & 0xff00) {
v >>= 8;
n += 8;
}
if (v & 0xf0) {
v >>= 4;
n += 4;
}
if (v & 0xc) {
v >>= 2;
n += 2;
}
if (v & 0x2) {
n++;
}
return n;
}
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* max compressed frame size */
#define MPA_MAX_CODED_FRAME_SIZE 1200
#define MPA_FRAME_SIZE 1152
#define SAMPLES_BUF_SIZE 4096
#define SBLIMIT 32 /* number of subbands */
#define DCT_BITS 14 /* number of bits for the DCT */
#define MUL(a,b) (((a) * (b)) >> DCT_BITS)
#define FIX(a) ((int)((a) * (1 << DCT_BITS)))
typedef struct MpegAudioContext {
PutBitContext pb;
int freq, bit_rate;
int lsf; /* 1 if mpeg2 low bitrate selected */
int bitrate_index; /* bit rate */
int freq_index;
int frame_size; /* frame size, in bits, without padding */
long long nb_samples; /* total number of samples encoded */
/* padding computation */
int frame_frac, frame_frac_incr, do_padding;
short samples_buf[SAMPLES_BUF_SIZE]; /* buffer for filter */
int samples_offset; /* offset in samples_buf */
int sb_samples[3][12][SBLIMIT];
unsigned char scale_factors[SBLIMIT][3]; /* scale factors */
unsigned char scale_code[SBLIMIT]; /* code to group 3 scale factors */
int sblimit; /* number of used subbands */
const unsigned char *alloc_table;
} MpegAudioContext;
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment