]> rtime.felk.cvut.cz Git - frescor/streamer.git/commitdiff
First import...
authorLuca Abeni <luca@nowhere.science.unitn.it>
Wed, 5 Nov 2008 10:37:31 +0000 (11:37 +0100)
committerLuca Abeni <luca@nowhere.science.unitn.it>
Wed, 5 Nov 2008 10:37:31 +0000 (11:37 +0100)
Makefile [new file with mode: 0644]
codec.c [new file with mode: 0644]
codec.h [new file with mode: 0644]
input.c [new file with mode: 0644]
input.h [new file with mode: 0644]
output.c [new file with mode: 0644]
output.h [new file with mode: 0644]
rt.c [new file with mode: 0644]
rt.h [new file with mode: 0644]
streamer.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..a5ab469
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,29 @@
+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)
+
diff --git a/codec.c b/codec.c
new file mode 100644 (file)
index 0000000..819343a
--- /dev/null
+++ b/codec.c
@@ -0,0 +1,135 @@
+#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;
+}
+
diff --git a/codec.h b/codec.h
new file mode 100644 (file)
index 0000000..13764da
--- /dev/null
+++ b/codec.h
@@ -0,0 +1,5 @@
+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);
diff --git a/input.c b/input.c
new file mode 100644 (file)
index 0000000..02a8b20
--- /dev/null
+++ b/input.c
@@ -0,0 +1,93 @@
+#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(&param, 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, &param);
+    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;
+}
diff --git a/input.h b/input.h
new file mode 100644 (file)
index 0000000..7fa7b9c
--- /dev/null
+++ b/input.h
@@ -0,0 +1,3 @@
+AVFormatContext *open_input_stream(const char *fname);
+void close_input_stream(AVFormatContext *s);
+AVPacket *read_input_packet(AVFormatContext *s);
diff --git a/output.c b/output.c
new file mode 100644 (file)
index 0000000..939be99
--- /dev/null
+++ b/output.c
@@ -0,0 +1,63 @@
+#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);
+}
+
diff --git a/output.h b/output.h
new file mode 100644 (file)
index 0000000..98a2a2e
--- /dev/null
+++ b/output.h
@@ -0,0 +1,3 @@
+int pkt_send(AVFormatContext *ctx, AVPacket *pkt);
+AVFormatContext *open_output_stream(const char *dst, int port, enum CodecType codec_type);
+
diff --git a/rt.c b/rt.c
new file mode 100644 (file)
index 0000000..34f859f
--- /dev/null
+++ b/rt.c
@@ -0,0 +1,19 @@
+/* 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);
+}
diff --git a/rt.h b/rt.h
new file mode 100644 (file)
index 0000000..28e7303
--- /dev/null
+++ b/rt.h
@@ -0,0 +1,2 @@
+void rt_job_start(uint64_t t);
+void rt_job_end(void);
diff --git a/streamer.c b/streamer.c
new file mode 100644 (file)
index 0000000..2774a7a
--- /dev/null
@@ -0,0 +1,76 @@
+#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;
+}
+