#ifndef RECORD_H
#define RECORD_H
#include "avcodec.h "
#include "avformat.h "
#include <stdio.h>
class QRecord
{
public:
static int Open(const char *,int,int,int);
static int AddFrame(unsigned char*,unsigned char*,unsigned char*);
static int Close();
static AVCodecContext *c;
static int out_size, outbuf_size;
static FILE *f;
static AVFrame *picture;
static uint8_t *outbuf;
};
#endif
================================
#include "Record.h "
#include <stdlib.h>
AVCodecContext *QRecord::c=NULL;
int QRecord::out_size, QRecord::outbuf_size;
FILE *QRecord::f;
AVFrame *QRecord::picture;
uint8_t *QRecord::outbuf;
int QRecord::Open(const char *filename,int width,int height,int frame_rate)
{
AVCodec *codec;
av_register_all();
codec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO);
if (!codec) {
fprintf(stderr, "codec not found\n ");
return -1;
}
c= avcodec_alloc_context();
picture= avcodec_alloc_frame();
/* put sample parameters */
c-> bit_rate = 400000;
/* resolution must be a multiple of two */
c-> width = width;
c-> height = height;
/* frames per second */
c-> frame_rate = frame_rate;
c-> frame_rate_base= 1;
c-> gop_size = 10; /* emit one intra frame every ten frames */
c-> max_b_frames=1;
/* open it */
if (avcodec_open(c, codec) < 0) {
fprintf(stderr, "could not open codec\n ");
return -1;
}
/* the codec gives us the frame size, in samples */
f = fopen(filename, "w ");
if (!f) {
fprintf(stderr, "could not open %s\n ", filename);
return -1;
}
/* alloc image and output buffer */
outbuf_size = 1000000;//?
outbuf =(uint8_t*) malloc(outbuf_size);
//size = c-> width * c-> height;
//picture_buf =(uint8_t*) malloc((size * 3) / 2); /* size for YUV 420 */
picture-> linesize[0] = c-> width;
picture-> linesize[1] = c-> width / 2;
picture-> linesize[2] = c-> width / 2;
return 0;
}
int QRecord::AddFrame(unsigned char *y,unsigned char *u,unsigned char *v)
{
picture-> data[0] = y;
picture-> data[1] = u;
picture-> data[2] = v;
out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture);
//printf( "encoding frame %3d (size=%5d)\n ", i, out_size);
fwrite(outbuf, 1, out_size, f);
return 0;
}
int QRecord::Close()
{
while(out_size) {
out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL);
//printf( "write frame %3d (size=%5d)\n ", i, out_size);
fwrite(outbuf, 1, out_size, f);
}
/* add sequence end code to have a real mpeg file */
outbuf[0] = 0x00;
outbuf[1] = 0x00;
outbuf[2] = 0x01;
outbuf[3] = 0xb7;
fwrite(outbuf, 1, 4, f);
fclose(f);
free(outbuf);
avcodec_close(c);
free(c);
free(picture);
//printf( "\n ");
return 0;
}
============================================
使用ffmpeg的库编码mpeg的技术总结报告
Sun Gang, 2003-11-21
一 . 概述
Ffmpeg是一个优秀的基于LGPL协议的视频/音频转换器.目前已经有很多多媒体应用软件使用它来作为编码器,如Xine,Mplayer,Xbox Media Player等.它也能用于从视频/音频源来抓取数据保存为视频音频文件.Ffmpeg还能从各种采样率来开始转换,能够通过高品质的多相滤波技术来实现放大缩小,频域相域的变换等.
这里,我们使用Ffmpeg来实现mpeg的编码过程.
二 . 摄像头的视频捕捉调用相关说明(即使用Video4Linux API获取图象的调用说明)
#include <videodev.h>
struct video_window vid_win;
struct video_capability vid_caps;
struct video_picture vid_pic;
struct video_mbuf mbuf;
1. 打开设备
int dev = open( "/dev/video0 ",O_RDWR);
2. 获取相关参数
ioctl (dev, VIDIOCGCAP, &vid_caps);
ioctl (dev, VIDIOCGWIN, &vid_win);
ioctl (dev, VIDIOCGPICT, &vid_pic);
//Check to see if we can use mmap
if(0 == ioctl(dev,VIDIOCGMBUF,&mbuf))...;
//Check to see if this camera uses MJPEG
if(vid_caps.type & VID_TYPE_MJPEG_ENCODER)...;
3. 设置相关参数
ioctl(dev, VIDIOCSPICT, &vid_pic);
ioctl(dev, VIDIOCSWIN, &vid_win);
4. 获取图象数据
read (dev, picbuff, size);
//至此,图象数据存放在picbuff中
三 . QRecord编码接口说明(编码为MPEG1 System format, 其中视频采用mpeg1video, 音频采用MP2)
定义如下
class QRecord
{
public:
//encode mpeg1 file with ffmpeg library
static int audio_input_frame_size;
static AVOutputFormat *fmt;
static AVFormatContext *oc;
static AVStream *audio_st,*video_st;
static int Open(const char* filename,int width,int height,int frame_rate,bool audio_on=false);
static int AddVideoFrame(uint8_t* y,uint8_t* u,uint8_t* v);
static int AddAudioFrame(int16_t* inbuf);
static int Close();
//for decompress Jpeg
static int DecompressJpeg(const char* input,unsigned char* rgbbuffer);
//for rgb2yuv convert
static int count ;
static float RGBYUV02990[256], RGBYUV05870[256], RGBYUV01140[256];
static float RGBYUV01684[256], RGBYUV03316[256];
static float RGBYUV04187[256], RGBYUV00813[256];
static void InitRGB2YUVLookupTable();
static int RGB2YUV (int x_dim, int y_dim, void *bmp, void *y_out, void *u_out, void *v_out, int flip);
static int add_scanline_to_rgbbuffer(unsigned char* linebuffer,int length,unsigned char* rgbbuffer);
};
几个重要接口函数说明,
QRecord::Open() 打开要存储文件,并初始化各项参数
QRecord::AddVideoFrame()增加一帧视频数据,格式为YUV420P,
QRecord::AddAudioFrame()增加一帧音频数据,格式为44.1KHz,16bits,2channels PCM data
QRecord::Close()关闭文件,释放内存等.
四 . 编码速度测试报告
测试数据为25张320X240,RGB24的图片文件,编码1000帧的各自需要时间如下:
VIA Cyrix 1G, 96M ram为 39-42秒
Intel PIII-M 800M, 128M ram 为6秒
Intel PIII 550M,128M ram为10 秒.