--- /dev/null
+FFSRC ?= $(FFDIR)
+CPPFLAGS= -I $(FFSRC)
+CFLAGS = -Wall
+CFLAGS += -Wdeclaration-after-statement
+CFLAGS += -Wno-switch -Wdisabled-optimization -Wpointer-arith -Wredundant-decls
+CFLAGS += -Wno-pointer-sign
+LDFLAGS= -L $(FFDIR)/libavutil -L $(FFDIR)/libavcodec -L $(FFDIR)/libavformat -L $(FFDIR)/libavdevice
+LDLIBS = -lavdevice -lavformat -lavcodec -lavutil
+
+LDLIBS += -lm -lz
+CFLAGS += -g
+
+OBJS = input.o codec.o output.o rt.o
+
+all: streamer
+
+streamer: streamer.o $(OBJS)
+
+clean:
+ rm -f *.o streamer *.d
+
+###################################
+%.d: %.c
+ $(CC) $(CPPFLAGS) -MM -MF $@ $<
+
+%.o: %.d
+
+-include $(OBJS:.o=.d)
+
--- /dev/null
+#include "libavformat/avformat.h"
+#include "libavcodec/avcodec.h"
+#include "libswscale/swscale.h"
+
+struct resample_data {
+ struct SwsContext *resample_ctx;
+ int in_height;
+ AVFrame resampled_frame;
+};
+
+int codec_open(AVFormatContext *ctx)
+{
+ AVCodec *codec;
+ int i, res;
+
+ for (i = 0; i < ctx->nb_streams; i++) {
+ codec = avcodec_find_decoder(ctx->streams[i]->codec->codec_id);
+ if (!codec) {
+ fprintf(stderr, "Cannot find codec %d for input stream %d\n",
+ ctx->streams[i]->codec->codec_id, i);
+ return -1;
+ }
+ res = avcodec_open(ctx->streams[i]->codec, codec);
+ if (res < 0) {
+ fprintf(stderr, "Cannot open codec for input stream %d\n", i);
+
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int out_codec_open(AVFormatContext *ctx)
+{
+ AVCodec *codec;
+ int i, res;
+
+ for (i = 0; i < ctx->nb_streams; i++) {
+ codec = avcodec_find_encoder(ctx->streams[i]->codec->codec_id);
+ if (!codec) {
+ fprintf(stderr, "Cannot find codec %d for output stream %d\n",
+ ctx->streams[i]->codec->codec_id, i);
+ return -1;
+ }
+ res = avcodec_open(ctx->streams[i]->codec, codec);
+ if (res < 0) {
+ fprintf(stderr, "Cannot open codec for input stream %d\n", i);
+
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
+AVFrame *pkt_decode(AVFormatContext *ctx, AVPacket *pkt)
+{
+ static AVFrame frame;
+ int res, got;
+
+ avcodec_get_frame_defaults(&frame);
+ res = avcodec_decode_video(ctx->streams[pkt->stream_index]->codec,
+ &frame, &got, pkt->data, pkt->size);
+ if (res < 0) {
+ got = res;
+ }
+
+ if (got > 0) {
+ AVFrame *res;
+ struct resample_data *r;
+
+ r = ctx->streams[pkt->stream_index]->codec->opaque;
+ if (r) {
+ sws_scale(r->resample_ctx, frame.data, frame.linesize, 0,
+ ctx->streams[pkt->stream_index]->codec->height,
+ r->resampled_frame.data, r->resampled_frame.linesize);
+ res = &r->resampled_frame;
+ } else {
+ res = &frame;
+ }
+
+ return res;
+ }
+
+ return NULL;
+}
+
+int codec_connect(AVCodecContext *ic, AVCodecContext *oc)
+{
+ struct resample_data *r;
+
+ if ((ic->width == oc->width) && (ic->height == oc->height) && (ic->pix_fmt == oc->pix_fmt)) {
+ return 0;
+ }
+
+ r = av_malloc(sizeof(struct resample_data));
+ r->resample_ctx = sws_getContext(ic->width, ic->height, ic->pix_fmt,
+ oc->width, oc->height, oc->pix_fmt,
+ SWS_BICUBIC, NULL, NULL, NULL);
+ if (r->resample_ctx == NULL) {
+ av_free(r);
+
+ return -1;
+ }
+ avcodec_get_frame_defaults(&r->resampled_frame);
+ avpicture_alloc((AVPicture*)&r->resampled_frame,
+ oc->pix_fmt, oc->width, oc->height);
+ ic->opaque = r;
+
+ return 1;
+}
+
+AVPacket *pkt_encode(AVFormatContext *ctx, AVFrame *frame)
+{
+ AVCodecContext *c = ctx->streams[0]->codec;
+ static AVPacket pkt;
+ int res;
+
+ if (pkt.data == NULL) {
+ pkt.size = 256 * 1024;
+ pkt.data = av_malloc(pkt.size);
+ }
+ res = avcodec_encode_video(c, pkt.data, pkt.size, frame);
+ if (c->coded_frame->pts != AV_NOPTS_VALUE) {
+ pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, ctx->streams[0]->time_base);
+ }
+ if (res < 0) {
+ return NULL;
+ }
+
+ return &pkt;
+}
+
--- /dev/null
+int codec_open(AVFormatContext *ctx);
+int out_codec_open(AVFormatContext *ctx);
+int codec_connect(AVCodecContext *ic, AVCodecContext *oc);
+AVFrame *pkt_decode(AVFormatContext *ctx, AVPacket *pkt);
+AVPacket *pkt_encode(AVFormatContext *ctx, AVFrame *frame);
--- /dev/null
+#include <string.h>
+#include "libavformat/avformat.h"
+#include "input.h"
+
+static uint64_t time_convert(uint64_t time, AVStream *st)
+{
+ if (st->start_time != AV_NOPTS_VALUE) {
+#if 1
+ time -= st->start_time;
+#else
+fprintf(stderr, "%Ld\t%Ld\n", st->start_time, av_rescale_q(st->start_time,
+ st->time_base, AV_TIME_BASE_Q));
+#endif
+ }
+ time = av_rescale_q(time, st->time_base, AV_TIME_BASE_Q);
+
+ return time;
+}
+
+static void time_base_convert(AVPacket *pkt, AVStream *st)
+{
+ if (pkt->pts != AV_NOPTS_VALUE) {
+ pkt->pts = time_convert(pkt->pts, st);
+ }
+ if (pkt->dts != AV_NOPTS_VALUE) {
+ pkt->dts = time_convert(pkt->dts, st);
+ }
+ if (pkt->duration != 0) {
+ pkt->duration = av_rescale_q(pkt->duration, st->time_base, AV_TIME_BASE_Q);
+ }
+}
+
+AVFormatContext *open_input_stream(const char *fname)
+{
+ AVFormatContext *s;
+ AVInputFormat *fmt;
+ AVFormatParameters param;
+ int res;
+
+ memset(¶m, 0, sizeof(AVFormatParameters));
+ /* FIXME: Set these!!! */
+ param.width = 352;
+ param.height = 288;
+ param.pix_fmt = PIX_FMT_YUV420P;
+ param.time_base.den = 25;
+ param.time_base.num = 1;
+ fmt = av_find_input_format("video4linux2");
+ res = av_open_input_file(&s, fname, fmt, 0, ¶m);
+ if (res < 0) {
+ fprintf(stderr, "Error opening %s: %d\n", fname, res);
+
+ return NULL;
+ }
+
+ res = av_find_stream_info(s);
+ if (res < 0) {
+ fprintf(stderr, "Cannot find codec parameters for %s\n", fname);
+
+ return NULL;
+ }
+
+ dump_format(s, 0, fname, 0);
+
+ return s;
+}
+
+void close_input_stream(AVFormatContext *s)
+{
+ av_close_input_file(s);
+}
+
+AVPacket *read_input_packet(AVFormatContext *s)
+{
+ static AVPacket pkt;
+ AVStream *st;
+ int res;
+
+ res = av_read_frame(s, &pkt);
+ if (res < 0) {
+ return NULL;
+ }
+
+ st = s->streams[pkt.stream_index];
+ if (pkt.dts == AV_NOPTS_VALUE) {
+ fprintf(stderr, "WTF??? Unknown DTS???\n");
+
+ return NULL;
+ }
+
+ time_base_convert(&pkt, st);
+
+ return &pkt;
+}
--- /dev/null
+AVFormatContext *open_input_stream(const char *fname);
+void close_input_stream(AVFormatContext *s);
+AVPacket *read_input_packet(AVFormatContext *s);
--- /dev/null
+#include "libavformat/avformat.h"
+
+
+AVFormatContext *open_output_stream(const char *dst, int port, enum CodecType codec_type)
+{
+ AVFormatContext *s;
+ static AVOutputFormat *rtp_format;
+ AVStream *st;
+
+ s = av_alloc_format_context();
+ rtp_format = guess_format("rtp", NULL, NULL);
+ if (!rtp_format) {
+ fprintf(stderr, "Unable for find the RTP format for output\n");
+
+ return NULL;
+ }
+
+ s->oformat = rtp_format;
+ st = av_new_stream(s, 0);
+ if (!st) {
+ fprintf(stderr, "Cannot allocate stream\n");
+
+ return NULL;
+ }
+
+ snprintf(s->filename, sizeof(s->filename), "rtp://%s:%d", dst, port);
+
+ /* open the UDP sockets for RTP and RTCP */
+ if (url_fopen(&s->pb, s->filename, URL_WRONLY) < 0) {
+ fprintf(stderr, "Cannot open '%s'\n", s->filename);
+ /* FIXME: Free the stream! */
+
+ return NULL;
+ }
+ avcodec_get_context_defaults2(s->streams[0]->codec, codec_type);
+ s->streams[0]->codec->codec_id = av_guess_codec(s->oformat, NULL, s->filename, NULL, codec_type);
+ s->streams[0]->codec->codec_id = CODEC_ID_MPEG4;
+ s->streams[0]->codec->pix_fmt = PIX_FMT_YUV420P;
+
+ return s;
+}
+
+int pkt_send(AVFormatContext *ctx, AVPacket *pkt)
+{
+ static int inited; /* FIXME: HACK! */
+
+
+ if (!inited) {
+ int res;
+
+fprintf(stderr,"initing!\n");
+ res = av_write_header(ctx);
+ if (res < 0) {
+ fprintf(stderr, "Cannot open the out RTP stream!\n");
+
+ return res;
+ }
+ inited = 1;
+ }
+
+ return av_write_frame(ctx, pkt);
+}
+
--- /dev/null
+int pkt_send(AVFormatContext *ctx, AVPacket *pkt);
+AVFormatContext *open_output_stream(const char *dst, int port, enum CodecType codec_type);
+
--- /dev/null
+/* FIXME: Dummy implementations!!! */
+#include <stdio.h>
+#include <libavformat/avformat.h>
+
+static uint64_t start_time, start_time1;
+
+void rt_job_start(uint64_t t)
+{
+ start_time = t;
+ start_time1 = av_gettime();
+}
+
+void rt_job_end(void)
+{
+ uint64_t t;
+
+ t = av_gettime();
+ printf("%Lu %Lu %Lu\t%Lu %Lu\n", start_time, start_time1, t, t - start_time, t - start_time1);
+}
--- /dev/null
+void rt_job_start(uint64_t t);
+void rt_job_end(void);
--- /dev/null
+#include "libavformat/avformat.h"
+#include "libavdevice/avdevice.h"
+
+#include "input.h"
+#include "output.h"
+#include "codec.h"
+#include "rt.h"
+
+static void sdp_print(AVFormatContext *s)
+{
+ char sdp[2048];
+ FILE *f;
+
+ f = fopen("sdp.txt", "w");
+ avf_sdp_create(&s, 1, sdp, sizeof(sdp));
+ fprintf(f, "%s\n", sdp);
+ fclose(f);
+}
+
+
+int main(int argc, char *argv[])
+{
+ AVFormatContext *s, *os;
+ int done;
+
+ avcodec_register_all();
+ av_register_all();
+ avdevice_register_all();
+
+ s = open_input_stream(argv[1]);
+ if (s == NULL) {
+ fprintf(stderr, "Cannot open input file %s\n", argv[1]);
+
+ return -1;
+ }
+ codec_open(s);
+ os = open_output_stream("224.10.20.30", 20000, CODEC_TYPE_VIDEO);
+ if (os == NULL) {
+ fprintf(stderr, "Cannot open output stream\n");
+
+ return -1;
+ }
+ os->streams[0]->codec->width = s->streams[0]->codec->width;
+ os->streams[0]->codec->height = s->streams[0]->codec->height;
+ os->streams[0]->codec->time_base = s->streams[0]->codec->time_base;
+ codec_connect(s->streams[0]->codec, os->streams[0]->codec);
+ out_codec_open(os);
+ dump_format(os, 0, os->filename, 1);
+ sdp_print(os);
+ done = 0;
+ while (!done) {
+ AVPacket *pkt;
+ pkt = read_input_packet(s);
+ if (pkt == NULL) {
+ done = 1;
+ } else {
+ AVFrame *f;
+ AVPacket *opkt;
+
+ pkt->pts += s->streams[pkt->stream_index]->start_time;
+ rt_job_start(pkt->pts);
+ f = pkt_decode(s, pkt);
+ if (f) {
+ opkt = pkt_encode(os, f);
+ if (opkt) {
+ pkt_send(os, opkt);
+ }
+ }
+ rt_job_end();
+ av_free_packet(pkt);
+ }
+ }
+
+ return 0;
+}
+