From 424b06efef61a3e4a58e9a6b77e8ed1d81e3a3d6 Mon Sep 17 00:00:00 2001 From: Ali Gholami Rudi Date: Tue, 19 Apr 2011 19:31:46 +0430 Subject: [PATCH] port of fbff to libmpeg3 --- Makefile | 3 +- ffs.c | 428 +++++++++++++++++++++++++-------------------------------------- 2 files changed, 172 insertions(+), 259 deletions(-) rewrite ffs.c (72%) diff --git a/Makefile b/Makefile index 53679e6..b6196fe 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,7 @@ FF_PATH = /opt CC = cc CFLAGS = -I$(FF_PATH)/include -Wall -O2 -LDFLAGS = -L$(FF_PATH)/lib -lavutil -lavformat -lavcodec -lavutil \ - -lswscale -lswresample -lz -lm -lpthread +LDFLAGS = -L$(FF_PATH)/lib -lmpeg3 -lpthread -lm all: fbff .c.o: diff --git a/ffs.c b/ffs.c dissimilarity index 72% index c7b4ec7..47c44b1 100644 --- a/ffs.c +++ b/ffs.c @@ -1,257 +1,171 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ffs.h" - -#define FFS_SAMPLEFMT AV_SAMPLE_FMT_S16 -#define FFS_CHLAYOUT AV_CH_LAYOUT_STEREO - -/* ffmpeg stream */ -struct ffs { - AVCodecContext *cc; - AVFormatContext *fc; - AVPacket pkt; - int si; /* stream index */ - long ts; /* frame timestamp (ms) */ - long seq; /* current position in this stream */ - long seq_all; /* seen packets after ffs_seek() */ - long seq_cur; /* decoded packet after ffs_seek() */ - - /* decoding video frames */ - struct SwsContext *swsc; - struct SwrContext *swrc; - AVFrame *dst; - AVFrame *tmp; -}; - -struct ffs *ffs_alloc(char *path, int flags) -{ - struct ffs *ffs; - int type = flags & FFS_VIDEO ? AVMEDIA_TYPE_VIDEO : AVMEDIA_TYPE_AUDIO; - int idx = (flags & FFS_STRIDX) - 1; - AVDictionary *opt = NULL; - ffs = malloc(sizeof(*ffs)); - memset(ffs, 0, sizeof(*ffs)); - ffs->si = -1; - if (avformat_open_input(&ffs->fc, path, NULL, NULL)) - goto failed; - if (avformat_find_stream_info(ffs->fc, NULL) < 0) - goto failed; - ffs->si = av_find_best_stream(ffs->fc, type, idx, -1, NULL, 0); - if (ffs->si < 0) - goto failed; - ffs->cc = ffs->fc->streams[ffs->si]->codec; - if (avcodec_open2(ffs->cc, avcodec_find_decoder(ffs->cc->codec_id), &opt)) - goto failed; - ffs->tmp = avcodec_alloc_frame(); - ffs->dst = avcodec_alloc_frame(); - return ffs; -failed: - ffs_free(ffs); - return NULL; -} - -void ffs_free(struct ffs *ffs) -{ - if (ffs->swrc) - swr_free(&ffs->swrc); - if (ffs->swsc) - sws_freeContext(ffs->swsc); - if (ffs->dst) - av_free(ffs->dst); - if (ffs->tmp) - av_free(ffs->tmp); - if (ffs->cc) - avcodec_close(ffs->cc); - if (ffs->fc) - avformat_close_input(&ffs->fc); - free(ffs); -} - -static AVPacket *ffs_pkt(struct ffs *ffs) -{ - AVPacket *pkt = &ffs->pkt; - while (av_read_frame(ffs->fc, pkt) >= 0) { - ffs->seq_all++; - if (pkt->stream_index == ffs->si) { - ffs->seq_cur++; - ffs->seq++; - return pkt; - } - av_free_packet(pkt); - } - return NULL; -} - -static long ts_ms(void) -{ - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_sec * 1000 + tv.tv_usec / 1000; -} - -static int wait(long ts, int vdelay) -{ - long nts = ts_ms(); - if (nts > ts && ts + vdelay > nts) { - usleep((ts + vdelay - nts) * 1000); - return 0; - } - return 1; -} - -#define MAX(a, b) ((a) < (b) ? (b) : (a)) - -void ffs_wait(struct ffs *ffs) -{ - AVRational *r = &ffs->fc->streams[ffs->si]->r_frame_rate; - int vdelay = 1000 * r->den / r->num; - if (!wait(ffs->ts, MAX(vdelay, 20))) - ffs->ts += MAX(vdelay, 20); - else - ffs->ts = ts_ms(); /* out of sync */ -} - -/* audio/video frame offset difference */ -int ffs_avdiff(struct ffs *ffs, struct ffs *affs) -{ - return affs->seq_all - ffs->seq_all; -} - -long ffs_pos(struct ffs *ffs, int diff) -{ - return (ffs->si << 28) | (ffs->seq + diff); -} - -void ffs_seek(struct ffs *ffs, long pos, int perframe) -{ - long idx = pos >> 28; - long seq = pos & 0x00ffffff; - av_seek_frame(ffs->fc, idx, seq * perframe, - perframe == 1 ? AVSEEK_FLAG_FRAME : 0); - ffs->seq = seq; - ffs->seq_all = 0; - ffs->seq_cur = 0; - ffs->ts = 0; -} - -void ffs_vinfo(struct ffs *ffs, int *w, int *h) -{ - *h = ffs->cc->height; - *w = ffs->cc->width; -} - -void ffs_ainfo(struct ffs *ffs, int *rate, int *bps, int *ch) -{ - *rate = ffs->cc->sample_rate; - *ch = av_get_channel_layout_nb_channels(FFS_CHLAYOUT); - *bps = 16; -} - -int ffs_vdec(struct ffs *ffs, void **buf) -{ - AVCodecContext *vcc = ffs->cc; - AVPacket *pkt = ffs_pkt(ffs); - int fine = 0; - if (!pkt) - return -1; - avcodec_decode_video2(vcc, ffs->tmp, &fine, pkt); - av_free_packet(pkt); - if (fine && buf) { - sws_scale(ffs->swsc, (void *) ffs->tmp->data, ffs->tmp->linesize, - 0, vcc->height, ffs->dst->data, ffs->dst->linesize); - *buf = (void *) ffs->dst->data[0]; - return ffs->dst->linesize[0]; - } - return 0; -} - -static int ffs_bytespersample(ffs) -{ - return av_get_bytes_per_sample(FFS_SAMPLEFMT) * - av_get_channel_layout_nb_channels(FFS_CHLAYOUT); -} - -int ffs_adec(struct ffs *ffs, void *buf, int blen) -{ - int rdec = 0; - AVPacket tmppkt = {0}; - AVPacket *pkt = ffs_pkt(ffs); - uint8_t *out[] = {NULL}; - if (!pkt) - return -1; - tmppkt.size = pkt->size; - tmppkt.data = pkt->data; - while (tmppkt.size > 0) { - int len, size; - len = avcodec_decode_audio4(ffs->cc, ffs->tmp, &size, &tmppkt); - if (len < 0) - break; - tmppkt.size -= len; - tmppkt.data += len; - if (size <= 0) - continue; - out[0] = buf + rdec; - len = swr_convert(ffs->swrc, - out, (blen - rdec) / ffs_bytespersample(ffs), - (void *) ffs->tmp->extended_data, ffs->tmp->nb_samples); - if (len > 0) - rdec += len * ffs_bytespersample(ffs); - } - av_free_packet(pkt); - return rdec; -} - -static int fbm2pixfmt(int fbm) -{ - switch (fbm & 0x0fff) { - case 0x888: - return PIX_FMT_RGB32; - case 0x565: - return PIX_FMT_RGB565; - case 0x233: - return PIX_FMT_RGB8; - default: - fprintf(stderr, "ffs: unknown fb_mode()\n"); - return PIX_FMT_RGB32; - } -} - -void ffs_vconf(struct ffs *ffs, float zoom, int fbm) -{ - int h = ffs->cc->height; - int w = ffs->cc->width; - int fmt = ffs->cc->pix_fmt; - int pixfmt = fbm2pixfmt(fbm); - uint8_t *buf = NULL; - int n; - ffs->swsc = sws_getContext(w, h, fmt, w * zoom, h * zoom, - pixfmt, SWS_FAST_BILINEAR | SWS_CPU_CAPS_MMX2, - NULL, NULL, NULL); - n = avpicture_get_size(pixfmt, w * zoom, h * zoom); - buf = av_malloc(n * sizeof(uint8_t)); - avpicture_fill((AVPicture *) ffs->dst, buf, pixfmt, w * zoom, h * zoom); -} - -void ffs_aconf(struct ffs *ffs) -{ - int rate, bps, ch; - ffs_ainfo(ffs, &rate, &bps, &ch); - ffs->swrc = swr_alloc_set_opts(NULL, - FFS_CHLAYOUT, FFS_SAMPLEFMT, rate, - ffs->cc->channel_layout, ffs->cc->sample_fmt, ffs->cc->sample_rate, - 0, NULL); - swr_init(ffs->swrc); -} - -void ffs_globinit(void) -{ - av_register_all(); - avformat_network_init(); -} +#include +#include +#include +#include +#include +#include +#include "libmpeg3.h" +#include "ffs.h" + +#define AUDIOBUF (1 << 14) +#define SEEKBYTES (1 << 12) + +/* ffmpeg stream */ +struct ffs { + mpeg3_t *file; + int si; /* stream index */ + + int fmt; /* video pixel format */ + int bpp; /* video bytes per pixel */ + long ts; /* frame timestamp (ms) */ + float zoom; /* video zoom */ + char vbuf[1 << 22]; /* video buffer */ +}; + +struct ffs *ffs_alloc(char *path, int flags) +{ + struct ffs *ffs; + int video = flags & FFS_VIDEO; + ffs = malloc(sizeof(*ffs)); + memset(ffs, 0, sizeof(*ffs)); + ffs->file = mpeg3_open(path, NULL); + if (!ffs->file) + goto failed; + if ((video && !mpeg3_has_video(ffs->file)) || !mpeg3_has_audio(ffs->file)) + goto failed; + mpeg3_set_cpus(ffs->file, 1); + return ffs; +failed: + ffs_free(ffs); + return NULL; +} + +void ffs_free(struct ffs *ffs) +{ + if (ffs->file) + mpeg3_close(ffs->file); + free(ffs); +} + +static long ts_ms(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000 + tv.tv_usec / 1000; +} + +static int wait(long ts, int vdelay) +{ + int nts = ts_ms(); + if (nts > ts && ts + vdelay > nts) { + usleep((ts + vdelay - nts) * 1000); + return 0; + } + return 1; +} + +void ffs_wait(struct ffs *ffs) +{ + int vdelay = 1000 / mpeg3_frame_rate(ffs->file, ffs->si); + if (!wait(ffs->ts, MAX(vdelay, 20))) + ffs->ts += MAX(vdelay, 20); + else + ffs->ts = ts_ms(); /* out of sync */ +} + +long ffs_pos(struct ffs *ffs, int diff) +{ + return mpeg3_tell_byte(ffs->file) + diff * SEEKBYTES; +} + +void ffs_seek(struct ffs *ffs, long pos, int perframe) +{ + mpeg3_seek_byte(ffs->file, pos); +} + +/* can more video packets be read */ +int ffs_avdiff(struct ffs *ffs, struct ffs *affs) +{ + return mpeg3_get_time(affs->file) - mpeg3_get_time(ffs->file); +} + +void ffs_vinfo(struct ffs *ffs, int *w, int *h) +{ + *h = mpeg3_video_height(ffs->file, ffs->si); + *w = mpeg3_video_width(ffs->file, ffs->si); +} + +void ffs_ainfo(struct ffs *ffs, int *rate, int *bps, int *ch) +{ + *rate = mpeg3_sample_rate(ffs->file, ffs->si); + *ch = mpeg3_audio_channels(ffs->file, ffs->si) == 1 ? 1 : 2; + *bps = 16; +} + +int ffs_vdec(struct ffs *ffs, void **buf) +{ + unsigned char *rows[1 << 11]; + int mw, mh, w, h; + int i; + int ret; + if (mpeg3_end_of_video(ffs->file, ffs->si)) + return -1; + ffs_vinfo(ffs, &mw, &mh); + w = mw * ffs->zoom; + h = mh * ffs->zoom; + for (i = 0; i < h; i++) + rows[i] = (void *) ffs->vbuf + i * w * ffs->bpp; + ret = mpeg3_read_frame(ffs->file, rows, 0, 0, mw, mh, w, h, ffs->fmt, ffs->si); + *buf = ffs->vbuf; + return ret ? 0 : w * ffs->bpp; +} + +int ffs_adec(struct ffs *ffs, void *buf, int blen) +{ + int16_t ch1[AUDIOBUF]; + int16_t ch2[AUDIOBUF]; + int16_t *out = buf; + int ch = mpeg3_audio_channels(ffs->file, ffs->si) == 1 ? 1 : 2; + int i; + if (mpeg3_end_of_audio(ffs->file, ffs->si)) + return -1; + if (mpeg3_read_audio(ffs->file, NULL, ch1, 0, AUDIOBUF, ffs->si)) + return 0; + if (ch > 1) + if (mpeg3_reread_audio(ffs->file, NULL, ch2, 1, AUDIOBUF, ffs->si)) + return 0; + for (i = 0; i < AUDIOBUF; i++) { + out[i * ch] = ch1[i]; + if (ch > 1) + out[i * ch + 1] = ch2[i]; + } + return AUDIOBUF * 4; +} + +static int fbm2pixfmt(int fbm) +{ + switch (fbm & 0x0fff) { + case 0x888: + return MPEG3_BGRA8888; + case 0x565: + return MPEG3_RGB565; + default: + fprintf(stderr, "ffs: unknown fb_mode()\n"); + return MPEG3_RGB888; + } +} + +void ffs_vconf(struct ffs *ffs, float zoom, int fbm) +{ + ffs->fmt = fbm2pixfmt(fbm); + ffs->zoom = zoom; + ffs->bpp = (fbm >> 16) & 0x0f; +} + +void ffs_aconf(struct ffs *ffs) +{ +} + +void ffs_globinit(void) +{ +} -- 2.11.4.GIT