Added initial support for transcoding.
This commit is contained in:
parent
84c1c05d73
commit
60bdb16c9d
11 changed files with 1578 additions and 5 deletions
3
Makefile
3
Makefile
|
@ -189,7 +189,8 @@ SRCS-$(CONFIG_AVAHI) += src/avahi.c
|
|||
|
||||
# libav
|
||||
SRCS-$(CONFIG_LIBAV) += src/libav.c \
|
||||
src/muxer/muxer_libav.c
|
||||
src/muxer/muxer_libav.c \
|
||||
src/plumbing/transcoding.c \
|
||||
|
||||
# CWC
|
||||
SRCS-${CONFIG_CWC} += src/cwc.c \
|
||||
|
|
4
configure
vendored
4
configure
vendored
|
@ -137,6 +137,10 @@ if enabled_or_auto libav; then
|
|||
has_libav=false
|
||||
fi
|
||||
|
||||
if $has_libav && ! check_pkg libswscale ">=0.13.0"; then
|
||||
has_libav=false
|
||||
fi
|
||||
|
||||
if $has_libav; then
|
||||
enable libav
|
||||
elif enabled libav; then
|
||||
|
|
|
@ -46,7 +46,9 @@
|
|||
#if ENABLE_TIMESHIFT
|
||||
#include "timeshift.h"
|
||||
#endif
|
||||
|
||||
#if ENABLE_LIBAV
|
||||
#include "plumbing/transcoding.h"
|
||||
#endif
|
||||
#include <sys/statvfs.h>
|
||||
#include "settings.h"
|
||||
#include <sys/time.h>
|
||||
|
@ -177,6 +179,10 @@ typedef struct htsp_subscription {
|
|||
streaming_target_t *hs_tshift;
|
||||
#endif
|
||||
|
||||
#if ENABLE_LIBAV
|
||||
streaming_target_t *hs_transcoder;
|
||||
#endif
|
||||
|
||||
htsp_msg_q_t hs_q;
|
||||
|
||||
time_t hs_last_report; /* Last queue status report sent */
|
||||
|
@ -282,13 +288,23 @@ htsp_subscription_destroy(htsp_connection_t *htsp, htsp_subscription_t *hs)
|
|||
{
|
||||
LIST_REMOVE(hs, hs_link);
|
||||
subscription_unsubscribe(hs->hs_s);
|
||||
|
||||
if(hs->hs_tsfix != NULL)
|
||||
tsfix_destroy(hs->hs_tsfix);
|
||||
|
||||
#if ENABLE_LIBAV
|
||||
if(hs->hs_transcoder != NULL)
|
||||
transcoder_destroy(hs->hs_transcoder);
|
||||
#endif
|
||||
|
||||
htsp_flush_queue(htsp, &hs->hs_q);
|
||||
|
||||
#if ENABLE_TIMESHIFT
|
||||
if(hs->hs_tshift)
|
||||
timeshift_destroy(hs->hs_tshift);
|
||||
#endif
|
||||
|
||||
|
||||
free(hs);
|
||||
}
|
||||
|
||||
|
@ -1328,6 +1344,32 @@ htsp_method_subscribe(htsp_connection_t *htsp, htsmsg_t *in)
|
|||
normts = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_LIBAV
|
||||
if (transcoding_enabled) {
|
||||
transcoder_props_t props;
|
||||
|
||||
props.tp_vcodec = streaming_component_txt2type(htsmsg_get_str(in, "videoCodec"));
|
||||
props.tp_acodec = streaming_component_txt2type(htsmsg_get_str(in, "audioCodec"));
|
||||
props.tp_scodec = streaming_component_txt2type(htsmsg_get_str(in, "subtitleCodec"));
|
||||
|
||||
props.tp_resolution = htsmsg_get_u32_or_default(in, "maxResolution", 0);
|
||||
props.tp_channels = htsmsg_get_u32_or_default(in, "channels", 0);
|
||||
props.tp_bandwidth = htsmsg_get_u32_or_default(in, "bandwidth", 0);
|
||||
|
||||
if ((str = htsmsg_get_str(in, "language")))
|
||||
strncpy(props.tp_language, str, 3);
|
||||
|
||||
if(props.tp_vcodec != SCT_UNKNOWN ||
|
||||
props.tp_acodec != SCT_UNKNOWN ||
|
||||
props.tp_scodec != SCT_UNKNOWN) {
|
||||
st = hs->hs_transcoder = transcoder_create(st);
|
||||
transcoder_set_properties(st, &props);
|
||||
normts = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(normts)
|
||||
st = hs->hs_tsfix = tsfix_create(st);
|
||||
|
||||
|
@ -1640,6 +1682,28 @@ htsp_method_file_seek(htsp_connection_t *htsp, htsmsg_t *in)
|
|||
return rep;
|
||||
}
|
||||
|
||||
|
||||
#if ENABLE_LIBAV
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static htsmsg_t *
|
||||
htsp_method_getCodecs(htsp_connection_t *htsp, htsmsg_t *in)
|
||||
{
|
||||
htsmsg_t *out, *l;
|
||||
|
||||
l = htsmsg_create_list();
|
||||
transcoder_get_capabilities(l);
|
||||
|
||||
out = htsmsg_create_map();
|
||||
|
||||
htsmsg_add_msg(out, "encoders", l);
|
||||
|
||||
return out;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* HTSP methods
|
||||
*/
|
||||
|
@ -1669,6 +1733,9 @@ struct {
|
|||
{ "subscriptionSkip", htsp_method_skip, ACCESS_STREAMING},
|
||||
{ "subscriptionSpeed", htsp_method_speed, ACCESS_STREAMING},
|
||||
{ "subscriptionLive", htsp_method_live, ACCESS_STREAMING},
|
||||
#if ENABLE_LIBAV
|
||||
{ "getCodecs", htsp_method_getCodecs, ACCESS_STREAMING},
|
||||
#endif
|
||||
{ "fileOpen", htsp_method_file_open, ACCESS_RECORDER},
|
||||
{ "fileRead", htsp_method_file_read, ACCESS_RECORDER},
|
||||
{ "fileClose", htsp_method_file_close, ACCESS_RECORDER},
|
||||
|
|
49
src/libav.c
49
src/libav.c
|
@ -91,6 +91,55 @@ streaming_component_type2codec_id(streaming_component_type_t type)
|
|||
return codec_id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Translate a libavcodec id to a component type
|
||||
*/
|
||||
streaming_component_type_t
|
||||
codec_id2streaming_component_type(enum CodecID id)
|
||||
{
|
||||
streaming_component_type_t type = CODEC_ID_NONE;
|
||||
|
||||
switch(id) {
|
||||
case CODEC_ID_H264:
|
||||
type = SCT_H264;
|
||||
break;
|
||||
case CODEC_ID_MPEG2VIDEO:
|
||||
type = SCT_MPEG2VIDEO;
|
||||
break;
|
||||
case CODEC_ID_AC3:
|
||||
type = SCT_AC3;
|
||||
break;
|
||||
case CODEC_ID_EAC3:
|
||||
type = SCT_EAC3;
|
||||
break;
|
||||
case CODEC_ID_AAC:
|
||||
type = SCT_AAC;
|
||||
break;
|
||||
case CODEC_ID_MP2:
|
||||
type = SCT_MPEG2AUDIO;
|
||||
break;
|
||||
case CODEC_ID_DVB_SUBTITLE:
|
||||
type = SCT_DVBSUB;
|
||||
break;
|
||||
case CODEC_ID_TEXT:
|
||||
type = SCT_TEXTSUB;
|
||||
break;
|
||||
case CODEC_ID_DVB_TELETEXT:
|
||||
type = SCT_TELETEXT;
|
||||
break;
|
||||
case CODEC_ID_NONE:
|
||||
type = SCT_NONE;
|
||||
break;
|
||||
default:
|
||||
type = SCT_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "tvheadend.h"
|
||||
|
||||
enum CodecID streaming_component_type2codec_id(streaming_component_type_t type);
|
||||
|
||||
streaming_component_type_t codec_id2streaming_component_type(enum CodecID id);
|
||||
void libav_init(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
#include "timeshift.h"
|
||||
#if ENABLE_LIBAV
|
||||
#include "libav.h"
|
||||
#include "plumbing/transcoding.h"
|
||||
#endif
|
||||
|
||||
/* Command line option struct */
|
||||
|
@ -126,6 +127,9 @@ const tvh_caps_t tvheadend_capabilities[] = {
|
|||
#if ENABLE_LINUXDVB
|
||||
{ "linuxdvb", NULL },
|
||||
#endif
|
||||
#if ENABLE_LIBAV
|
||||
{ "transcoding", &transcoding_enabled },
|
||||
#endif
|
||||
#if ENABLE_IMAGECACHE
|
||||
{ "imagecache", &imagecache_enabled },
|
||||
#endif
|
||||
|
|
1336
src/plumbing/transcoding.c
Normal file
1336
src/plumbing/transcoding.c
Normal file
File diff suppressed because it is too large
Load diff
42
src/plumbing/transcoding.h
Normal file
42
src/plumbing/transcoding.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* Transcoding
|
||||
* Copyright (C) 2013 John Törnblom
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "tvheadend.h"
|
||||
#include "htsmsg.h"
|
||||
|
||||
typedef struct transcoder_prop {
|
||||
streaming_component_type_t tp_vcodec;
|
||||
streaming_component_type_t tp_acodec;
|
||||
streaming_component_type_t tp_scodec;
|
||||
|
||||
int8_t tp_channels;
|
||||
int32_t tp_bandwidth;
|
||||
char tp_language[4];
|
||||
int32_t tp_resolution;
|
||||
} transcoder_props_t;
|
||||
|
||||
extern uint32_t transcoding_enabled;
|
||||
|
||||
streaming_target_t *transcoder_create (streaming_target_t *output);
|
||||
void transcoder_destroy(streaming_target_t *tr);
|
||||
|
||||
void transcoder_get_capabilities(htsmsg_t *array);
|
||||
void transcoder_set_properties (streaming_target_t *tr,
|
||||
transcoder_props_t *prop);
|
||||
|
12
src/psi.c
12
src/psi.c
|
@ -908,6 +908,8 @@ psi_caid2name(uint16_t caid)
|
|||
*
|
||||
*/
|
||||
static struct strtab streamtypetab[] = {
|
||||
{ "NONE", SCT_NONE },
|
||||
{ "UNKNOWN", SCT_UNKNOWN },
|
||||
{ "MPEG2VIDEO", SCT_MPEG2VIDEO },
|
||||
{ "MPEG2AUDIO", SCT_MPEG2AUDIO },
|
||||
{ "H264", SCT_H264 },
|
||||
|
@ -920,7 +922,7 @@ static struct strtab streamtypetab[] = {
|
|||
{ "MPEGTS", SCT_MPEGTS },
|
||||
{ "TEXTSUB", SCT_TEXTSUB },
|
||||
{ "EAC3", SCT_EAC3 },
|
||||
{ "AAC", SCT_MP4A },
|
||||
{ "AAC", SCT_MP4A },
|
||||
};
|
||||
|
||||
|
||||
|
@ -933,6 +935,14 @@ streaming_component_type2txt(streaming_component_type_t s)
|
|||
return val2str(s, streamtypetab) ?: "INVALID";
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
streaming_component_type_t
|
||||
streaming_component_txt2type(const char *str)
|
||||
{
|
||||
return str ? str2val(str, streamtypetab) : SCT_UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store service settings into message
|
||||
|
|
|
@ -184,6 +184,7 @@ int get_device_connection(const char *dev);
|
|||
* Stream component types
|
||||
*/
|
||||
typedef enum {
|
||||
SCT_NONE = -1,
|
||||
SCT_UNKNOWN = 0,
|
||||
SCT_MPEG2VIDEO = 1,
|
||||
SCT_MPEG2AUDIO,
|
||||
|
@ -423,7 +424,7 @@ typedef struct sbuf {
|
|||
} sbuf_t;
|
||||
|
||||
|
||||
|
||||
streaming_component_type_t streaming_component_txt2type(const char *str);
|
||||
const char *streaming_component_type2txt(streaming_component_type_t s);
|
||||
|
||||
static inline unsigned int tvh_strhash(const char *s, unsigned int mod)
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "psi.h"
|
||||
#include "plumbing/tsfix.h"
|
||||
#include "plumbing/globalheaders.h"
|
||||
#include "plumbing/transcoding.h"
|
||||
#include "epg.h"
|
||||
#include "muxer.h"
|
||||
#include "dvb/dvb.h"
|
||||
|
@ -548,6 +549,47 @@ page_http_playlist(http_connection_t *hc, const char *remain, void *opaque)
|
|||
}
|
||||
|
||||
|
||||
#if ENABLE_LIBAV
|
||||
static int
|
||||
http_get_transcoder_properties(struct http_arg_list *args,
|
||||
transcoder_props_t *props)
|
||||
{
|
||||
int transcode;
|
||||
const char *s;
|
||||
|
||||
memset(props, 0, sizeof(transcoder_props_t));
|
||||
|
||||
if ((s = http_arg_get(args, "transcode")))
|
||||
transcode = atoi(s);
|
||||
else
|
||||
transcode = 0;
|
||||
|
||||
if ((s = http_arg_get(args, "resolution")))
|
||||
props->tp_resolution = atoi(s);
|
||||
|
||||
if ((s = http_arg_get(args, "channels")))
|
||||
props->tp_channels = atoi(s);
|
||||
|
||||
if ((s = http_arg_get(args, "bandwidth")))
|
||||
props->tp_bandwidth = atoi(s);
|
||||
|
||||
if ((s = http_arg_get(args, "language")))
|
||||
strncpy(props->tp_language, s, 3);
|
||||
|
||||
if ((s = http_arg_get(args, "vcodec")))
|
||||
props->tp_vcodec = streaming_component_txt2type(s);
|
||||
|
||||
if ((s = http_arg_get(args, "acodec")))
|
||||
props->tp_acodec = streaming_component_txt2type(s);
|
||||
|
||||
if ((s = http_arg_get(args, "scodec")))
|
||||
props->tp_scodec = streaming_component_txt2type(s);
|
||||
|
||||
return transcode && transcoding_enabled;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Subscribes to a service and starts the streaming loop
|
||||
*/
|
||||
|
@ -660,6 +702,9 @@ http_stream_channel(http_connection_t *hc, channel_t *ch)
|
|||
streaming_target_t *gh;
|
||||
streaming_target_t *tsfix;
|
||||
streaming_target_t *st;
|
||||
#if ENABLE_LIBAV
|
||||
streaming_target_t *tr = NULL;
|
||||
#endif
|
||||
dvr_config_t *cfg;
|
||||
int priority = 100;
|
||||
int flags;
|
||||
|
@ -689,6 +734,14 @@ http_stream_channel(http_connection_t *hc, channel_t *ch)
|
|||
} else {
|
||||
streaming_queue_init2(&sq, 0, qsize);
|
||||
gh = globalheaders_create(&sq.sq_st);
|
||||
#if ENABLE_LIBAV
|
||||
transcoder_props_t props;
|
||||
if(http_get_transcoder_properties(&hc->hc_req_args, &props)) {
|
||||
tr = transcoder_create(gh);
|
||||
transcoder_set_properties(tr, &props);
|
||||
tsfix = tsfix_create(tr);
|
||||
} else
|
||||
#endif
|
||||
tsfix = tsfix_create(gh);
|
||||
st = tsfix;
|
||||
flags = 0;
|
||||
|
@ -710,6 +763,12 @@ http_stream_channel(http_connection_t *hc, channel_t *ch)
|
|||
|
||||
if(gh)
|
||||
globalheaders_destroy(gh);
|
||||
|
||||
#if ENABLE_LIBAV
|
||||
if(tr)
|
||||
transcoder_destroy(tr);
|
||||
#endif
|
||||
|
||||
if(tsfix)
|
||||
tsfix_destroy(tsfix);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue