diff --git a/src/avgen.c b/src/avgen.c deleted file mode 100644 index edc0bd74..00000000 --- a/src/avgen.c +++ /dev/null @@ -1,490 +0,0 @@ -/* - * A/V generator, for test purposes - * Copyright (C) 2007 Andreas Öman - * Copyright (c) 2007 Nicolas George - * - * 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 3 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, see . - */ - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include - -#include "tvhead.h" -#include "avgen.h" -#include "channels.h" -#include "dispatch.h" -#include "transports.h" -#include "buffer.h" -#include "parsers.h" - - -typedef struct avgen { - - AVCodecContext *avctx[2]; - - int16_t *audioframe; - - AVFrame videoframe; - - int video_duration; - int audio_duration; - - int64_t video_next; - int64_t audio_next; - - int64_t refclock; - - uint8_t *video_outbuf; - int video_outbuf_size; - - uint8_t *audio_outbuf; - int audio_outbuf_size; - - dtimer_t timer; - -} avgen_t; - - -static void avgen_deliver(th_transport_t *t, avgen_t *avg, int64_t clk); - -static void avgen_stop_feed(th_transport_t *t); - -static int avgen_start_feed(th_transport_t *t, unsigned int weight, - int status, int force_start); - -static void update_video(avgen_t *avg, int vframe, int framerate); -static void update_audio(avgen_t *avg, int vframe, int framerate); - -static void init_picture(avgen_t *avg, int w, int h); - -/* - * - */ -void -avgen_init(void) -{ - channel_t *ch; - th_transport_t *t; - - if(avcodec_find_encoder(CODEC_ID_MPEG2VIDEO) == NULL) - return; - - if(avcodec_find_encoder(CODEC_ID_MP2) == NULL) - return; - - ch = channel_find_by_name("Test PAL", 1); - - t = calloc(1, sizeof(th_transport_t)); - - t->tht_type = TRANSPORT_AVGEN; - t->tht_start_feed = avgen_start_feed; - t->tht_stop_feed = avgen_stop_feed; - - t->tht_video = transport_add_stream(t, -1, HTSTV_MPEG2VIDEO); - t->tht_video->st_tb = (AVRational){1, 1000000}; - - t->tht_audio = transport_add_stream(t, -1, HTSTV_MPEG2AUDIO); - t->tht_audio->st_tb = (AVRational){1, 1000000}; - - t->tht_name = strdup(ch->ch_name); - t->tht_provider = strdup("HTS Tvheadend"); - - t->tht_identifier = strdup("test1"); - - transport_map_channel(t, ch); -} - - - - - -/* - * - */ -static void -avgen_stop_feed(th_transport_t *t) -{ - avgen_t *avg = t->tht_avgen; - - av_free(avg->video_outbuf); - av_free(avg->audio_outbuf); - - avcodec_close(avg->avctx[0]); - avcodec_close(avg->avctx[1]); - - av_free(avg->audioframe); - - dtimer_disarm(&avg->timer); - av_free(avg->videoframe.data[0]); - free(avg); - - t->tht_runstatus = TRANSPORT_IDLE; -} - - - -/* - * - */ - -static void -rgb2yuv(uint8_t yuv[3], const uint8_t rgb[3]) -{ - int R = rgb[0]; - int G = rgb[1]; - int B = rgb[2]; - - int Y = ( ( 66 * R + 129 * G + 25 * B + 128) >> 8) + 16; - int U = ( ( -38 * R - 74 * G + 112 * B + 128) >> 8) + 128; - int V = ( ( 112 * R - 94 * G - 18 * B + 128) >> 8) + 128; - - yuv[0] = Y; - yuv[1] = U; - yuv[2] = V; -} - - -/* - * - */ -static int -avgen_start_feed(th_transport_t *t, unsigned int weight, int status, - int force_start) -{ - avgen_t *avg; - AVCodecContext *avctx; - AVCodec *c; - - avg = calloc(1, sizeof(avgen_t)); - - /* Open video */ - - c = avcodec_find_encoder(CODEC_ID_MPEG2VIDEO); - avctx = avg->avctx[0] = avcodec_alloc_context(); - - avctx->codec_type = CODEC_TYPE_VIDEO; - avctx->bit_rate = 1000000; - avctx->width = 768; - avctx->height = 576; - avctx->time_base.den = 25; - avctx->time_base.num = 1; - avctx->pix_fmt = PIX_FMT_YUV420P; - avctx->gop_size = 12; - avctx->max_b_frames = 2; - - avg->video_duration = 1000000 / 25; - - - if(avcodec_open(avg->avctx[0], c)) { - return -1; - } - - avpicture_alloc((AVPicture *)&avg->videoframe, PIX_FMT_YUV420P, - avctx->width, avctx->height); - - init_picture(avg, avctx->width, avctx->height); - - /* Open audio */ - - c = avcodec_find_encoder(CODEC_ID_MP2); - avctx = avg->avctx[1] = avcodec_alloc_context(); - - avctx->codec_type = CODEC_TYPE_AUDIO; - avctx->channels = 2; - avctx->sample_rate = 48000; - avctx->bit_rate = 256000; - - if(avcodec_open(avg->avctx[1], c)) { - return -1; - } - - avg->audio_duration = 1000000 * avctx->frame_size / avctx->sample_rate; - avg->audioframe = av_malloc(avctx->frame_size * 2 * sizeof(int16_t)); - - - /* All done, setup output buffers and start */ - - avg->video_outbuf_size = 200000; - avg->video_outbuf = av_malloc(avg->video_outbuf_size); - - avg->audio_outbuf_size = 20000; - avg->audio_outbuf = av_malloc(avg->audio_outbuf_size); - - t->tht_avgen = avg; - - t->tht_runstatus = TRANSPORT_RUNNING; - - avg->refclock = getclock_hires(); - avgen_deliver(t, avg, avg->refclock); - return 0; -} - -/** - * - */ -static void -avgen_enqueue(th_transport_t *t, th_stream_t *st, int64_t dts, int64_t pts, - int duration, uint8_t *data, int datalen) -{ - th_pkt_t *pkt; - - avgstat_add(&st->st_rate, datalen, dispatch_clock); - - pkt = pkt_alloc(data, datalen, pts, dts); - pkt->pkt_duration = duration; - - parser_enqueue_packet(t, st, pkt); -} - - -static void -avg_timer_callback(void *aux, int64_t now) -{ - th_transport_t *t = aux; - avgen_deliver(t, t->tht_avgen, now); -} - - -/** - * - */ -static void -avgen_deliver(th_transport_t *t, avgen_t *avg, int64_t clk0) -{ - int r; - int64_t pts, clk, nxt; - int64_t vframe; - - vframe = avg->video_next * avg->avctx[0]->time_base.den / 1000000; - - AVCodecContext *avctx; - - clk = clk0 - avg->refclock; - - if(avg->video_next <= clk) { - update_video(avg, vframe, avg->avctx[0]->time_base.den); - avctx = avg->avctx[0]; - avg->videoframe.pts = AV_NOPTS_VALUE; - - r = avcodec_encode_video(avctx, avg->video_outbuf, avg->video_outbuf_size, - &avg->videoframe); - - if(r > 0) { - pts = AV_NOPTS_VALUE; - avgen_enqueue(t, t->tht_video, avg->video_next, pts, avg->video_duration, - avg->video_outbuf, r); - - } - avg->video_next += avg->video_duration; - } - - - if(avg->audio_next <= clk) { - update_audio(avg, vframe, avg->avctx[0]->time_base.den); - avctx = avg->avctx[1]; - r = avcodec_encode_audio(avctx, avg->audio_outbuf, avg->audio_outbuf_size, - avg->audioframe); - - if(r > 0) { - avgen_enqueue(t, t->tht_audio, avg->audio_next, avg->audio_next, - avg->audio_duration, - avg->audio_outbuf, r); - - } - avg->audio_next += avg->audio_duration; - } - - nxt = FFMIN(avg->audio_next, avg->video_next) + avg->refclock; - - if(nxt < clk0 + 1000) - nxt = clk0 + 1000; - - dtimer_arm_hires(&avg->timer, avg_timer_callback, t, nxt); -} - - - -/** - * - */ -static void -draw_rectangle(unsigned val, unsigned char *p, unsigned stride, - unsigned sw, unsigned x, unsigned y, unsigned w, unsigned h) -{ - unsigned i; - - p += sw * (x + y * stride); - w *= sw; - h *= sw; - for(i = 0; i < h; i++) { - memset(p, val, w); - p += stride; - } -} - -/** - * - */ -static void -draw_digit(int digit, unsigned char *p0, unsigned stride, unsigned sw) -{ - static const unsigned char masks[10] = { - 0x7D, 0x50, 0x37, 0x57, 0x5A, 0x4F, 0x6F, 0x51, 0x7F, 0x5F - }; - unsigned mask = masks[digit]; - - draw_rectangle(0, p0, stride, sw, 0, 0, 8, 13); - if(mask & 1) - draw_rectangle(255, p0, stride, sw, 1, 0, 5, 1); - if(mask & 2) - draw_rectangle(255, p0, stride, sw, 1, 6, 5, 1); - if(mask & 4) - draw_rectangle(255, p0, stride, sw, 1, 12, 5, 1); - if(mask & 8) - draw_rectangle(255, p0, stride, sw, 0, 1, 1, 5); - if(mask & 16) - draw_rectangle(255, p0, stride, sw, 6, 1, 1, 5); - if(mask & 32) - draw_rectangle(255, p0, stride, sw, 0, 7, 1, 5); - if(mask & 64) - draw_rectangle(255, p0, stride, sw, 6, 7, 1, 5); -} - -/** - * - */ -static void -update_video(avgen_t *avg, int vframe, int framerate) -{ - int frame, sec, min, d; - unsigned char *p; - int segsize, offset; - int as; - - frame = vframe % framerate; - vframe /= framerate; - - sec = vframe % 60; - vframe /= 60; - - min = vframe; - - - as = sec & 1 ? 255 : 0; - - p = avg->videoframe.data[0]; - offset = avg->videoframe.linesize[0] * 3; - - draw_rectangle(~as, p + offset + 30, avg->videoframe.linesize[0], - 4, 0, 0, 8, 13); - - draw_rectangle(as, p + offset + 700, avg->videoframe.linesize[0], - 4, 0, 0, 8, 13); - - offset += 500; - - segsize = 4; - - d = frame % 10; - draw_digit(d, p + offset , avg->videoframe.linesize[0], segsize); - offset -= 40; - d = frame / 10; - draw_digit(d, p + offset , avg->videoframe.linesize[0], segsize); - - offset -= 60; - - d = sec % 10; - draw_digit(d, p + offset , avg->videoframe.linesize[0], segsize); - offset -= 40; - d = sec / 10; - draw_digit(d, p + offset , avg->videoframe.linesize[0], segsize); - - offset -= 60; - - d = min % 10; - draw_digit(d, p + offset , avg->videoframe.linesize[0], segsize); - offset -= 40; - d = min / 10; - draw_digit(d, p + offset , avg->videoframe.linesize[0], segsize); - -} - -/** - * - */ -static void -update_audio(avgen_t *avg, int vframe, int framerate) -{ - int frame, i, j; - float f; - - AVCodecContext *avctx = avg->avctx[1]; - frame = vframe % framerate; - vframe /= framerate; - - if(frame < 2) { - j = vframe & 1; - for(i = 0; i < avctx->frame_size; i++) { - f = sin(M_PI * 2 * (float)i / (float)avctx->frame_size * 20); - avg->audioframe[i * 2 + j] = f * 20000; - } - } else { - memset(avg->audioframe, 0, avctx->frame_size * 2 * sizeof(int16_t)); - } -} - - -/** - * - */ -static void -init_picture(avgen_t *avg, int w, int h) -{ - uint8_t rgb[3] = {0, 0, 0}; - uint8_t yuv[3]; - int i; - - for(i = 0; i < h; i++) { - rgb[2] = 255 * ((float)i / (float)h); - rgb2yuv(yuv, rgb); - memset(avg->videoframe.data[0] + i * avg->videoframe.linesize[0], - yuv[0], w); - } - - for(i = 0; i < h / 2; i++) { - - rgb[2] = 255 * ((float)i / (float)(h / 2)); - rgb2yuv(yuv, rgb); - - memset(avg->videoframe.data[1] + i * avg->videoframe.linesize[1], - yuv[1], w / 2); - memset(avg->videoframe.data[2] + i * avg->videoframe.linesize[2], - yuv[2], w / 2); - } -} diff --git a/src/avgen.h b/src/avgen.h deleted file mode 100644 index 25aaa4f7..00000000 --- a/src/avgen.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * A/V generator, for test purposes - * Copyright (C) 2007 Andreas Öman - * - * 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 3 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, see . - */ - -#ifndef AVGEN_H_ -#define AVGEN_H_ - -void avgen_init(void); - -#endif /* AVGEN_H */ diff --git a/src/file_input.c b/src/file_input.c deleted file mode 100644 index 83a7a67e..00000000 --- a/src/file_input.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Circular streaming from a file - * Copyright (C) 2008 Andreas Öman - * - * 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 3 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, see . - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include - -#include - -#include "tvhead.h" -#include "file_input.h" -#include "channels.h" -#include "dispatch.h" -#include "transports.h" -#include "parsers.h" -#include "buffer.h" - -#include - -typedef struct file_input { - AVFormatContext *fi_fctx; - const char *fi_name; - dtimer_t fi_timer; - int64_t fi_refclock; - int64_t fi_dts_offset; - int64_t fi_last_dts; - - th_pkt_t *fi_next; - -} file_input_t; - - -static void file_input_stop_feed(th_transport_t *t); - -static int file_input_start_feed(th_transport_t *t, unsigned int weight, - int status, int force_start); - -static void fi_deliver(void *aux, int64_t now); - -static void file_input_get_pkt(th_transport_t *t, file_input_t *fi, - int64_t now); - - - -static const char *file_input_source_name(th_transport_t *t) -{ - return "file input"; -} - - -/* - * - */ -void -file_input_init(void) -{ - const char *s; - file_input_t *fi; - int i; - AVFormatContext *fctx; - AVCodecContext *ctx; - config_entry_t *ce; - th_transport_t *t; - th_stream_t *st; - channel_t *ch; - - TAILQ_FOREACH(ce, &config_list, ce_link) { - if(ce->ce_type != CFG_SUB || strcasecmp("streamedfile", ce->ce_key)) - continue; - - if((s = config_get_str_sub(&ce->ce_sub, "file", NULL)) == NULL) - continue; - - if(av_open_input_file(&fctx, s, NULL, 0, NULL) != 0) { - syslog(LOG_ERR, "streamedfile: Unable to open file \"%s\"", s); - continue; - } - - // fctx->flags |= AVFMT_FLAG_GENPTS; - - if(av_find_stream_info(fctx) < 0) { - av_close_input_file(fctx); - syslog(LOG_ERR, "streamedfile: \"%s\": Unable to probe file format", s); - continue; - } - - dump_format(fctx, 0, s, 0); - - fi = calloc(1, sizeof(file_input_t)); - - fi->fi_fctx = fctx; - fi->fi_name = strdup(s); - - t = calloc(1, sizeof(th_transport_t)); - - t->tht_type = TRANSPORT_STREAMEDFILE; - t->tht_start_feed = file_input_start_feed; - t->tht_stop_feed = file_input_stop_feed; - - for(i = 0; i < fctx->nb_streams; i++) { - ctx = fctx->streams[i]->codec; - - switch(ctx->codec_id) { - case CODEC_ID_H264: - transport_add_stream(t, i, HTSTV_H264); - break; - - case CODEC_ID_MPEG2VIDEO: - st = transport_add_stream(t, i, HTSTV_MPEG2VIDEO); - st->st_vbv_delay = -1; - st->st_vbv_size = 229376; - break; - - case CODEC_ID_MP2: - case CODEC_ID_MP3: - if(ctx->sub_id == 2) - transport_add_stream(t, i, HTSTV_MPEG2AUDIO); - break; - - case CODEC_ID_AC3: - transport_add_stream(t, i, HTSTV_AC3); - break; - - default: - break; - } - } - - if((s = config_get_str_sub(&ce->ce_sub, "channel", NULL)) == NULL) - continue; - - ch = channel_find_by_name(s, 1); - - - t->tht_name = strdup(ch->ch_name); - t->tht_provider = strdup("HTS Tvheadend"); - t->tht_identifier = strdup(ch->ch_name); - t->tht_file_input = fi; - t->tht_sourcename = file_input_source_name; - transport_map_channel(t, ch); - } -} - - - - - -/* - * - */ -static void -file_input_stop_feed(th_transport_t *t) -{ - file_input_t *fi = t->tht_file_input; - - dtimer_disarm(&fi->fi_timer); - t->tht_runstatus = TRANSPORT_IDLE; -} - - - - -static void -file_input_reset(th_transport_t *t, file_input_t *fi) -{ - av_seek_frame(fi->fi_fctx, -1, 0, AVSEEK_FLAG_BACKWARD); - t->tht_dts_start = AV_NOPTS_VALUE; -} - - -/* - * - */ -static int -file_input_start_feed(th_transport_t *t, unsigned int weight, int status, - int force_start) -{ - file_input_t *fi = t->tht_file_input; - - t->tht_runstatus = TRANSPORT_RUNNING; - - file_input_reset(t, fi); - fi->fi_refclock = getclock_hires(); - fi->fi_dts_offset = AV_NOPTS_VALUE; - - dtimer_arm(&fi->fi_timer, fi_deliver, t, 1); - return 0; -} - - -/* - * - */ -static void -file_input_get_pkt(th_transport_t *t, file_input_t *fi, int64_t now) -{ - AVPacket ffpkt; - th_pkt_t *pkt; - th_stream_t *st; - int i; - int64_t dts, pts, errcnt = 0, dt; - - again: - i = av_read_frame(fi->fi_fctx, &ffpkt); - if(i < 0) { - fi->fi_dts_offset += fi->fi_last_dts; - file_input_reset(t, fi); - fi->fi_next = NULL; - - if(errcnt == 0) { - errcnt++; - goto again; - } - - syslog(LOG_ERR, "streamedfile: Unable to read from file \"%s\"", - fi->fi_name); - return; - } - - LIST_FOREACH(st, &t->tht_streams, st_link) - if(st->st_pid == ffpkt.stream_index) - break; - - if(st == NULL) - goto again; - - /* Update stream timebase */ - st->st_tb = fi->fi_fctx->streams[ffpkt.stream_index]->time_base; - - assert(ffpkt.dts != AV_NOPTS_VALUE); /* fixme */ - - if(fi->fi_dts_offset == AV_NOPTS_VALUE) - fi->fi_dts_offset = ffpkt.dts; - - fi->fi_last_dts = ffpkt.dts; - dts = ffpkt.dts + fi->fi_dts_offset; - - pts = ffpkt.pts; - if(pts != AV_NOPTS_VALUE) - pts += fi->fi_dts_offset; - - pkt = pkt_alloc(ffpkt.data, ffpkt.size, pts, dts); - pkt->pkt_duration = 0; - pkt->pkt_stream = st; - - fi->fi_next = pkt; - - /* compute delivery time */ - - dt = av_rescale_q(dts, st->st_tb, AV_TIME_BASE_Q) + fi->fi_refclock; - dtimer_arm_hires(&fi->fi_timer, fi_deliver, t, dt); -} - -static void -fi_deliver(void *aux, int64_t now) -{ - th_transport_t *t = aux; - file_input_t *fi = t->tht_file_input; - th_stream_t *st; - - if(fi->fi_next != NULL) { - st = fi->fi_next->pkt_stream; - fi->fi_next->pkt_stream = NULL; /* this must be null upon enqueue */ - parser_enqueue_packet(t, st, fi->fi_next); - fi->fi_next = NULL; - } - - file_input_get_pkt(t, fi, now); -} diff --git a/src/file_input.h b/src/file_input.h deleted file mode 100644 index 26a857ed..00000000 --- a/src/file_input.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Circular streaming from a file - * Copyright (C) 2008 Andreas Öman - * - * 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 3 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, see . - */ - -#ifndef FILE_INPUT_H_ -#define FILE_INPUT_H_ - -void file_input_init(void); - -#endif /* FILE_INPUT_H */