transcoding: added initial support for vorbis. might suffer from sync problems when frames are dropped earlier in the pipe line

This commit is contained in:
John Törblom 2013-07-17 16:26:48 +02:00
parent e4b9f5960d
commit 08bd137d6f
8 changed files with 102 additions and 4 deletions

View file

@ -77,6 +77,9 @@ streaming_component_type2codec_id(streaming_component_type_t type)
case SCT_MPEG2AUDIO: case SCT_MPEG2AUDIO:
codec_id = CODEC_ID_MP2; codec_id = CODEC_ID_MP2;
break; break;
case SCT_VORBIS:
codec_id = CODEC_ID_VORBIS;
break;
case SCT_DVBSUB: case SCT_DVBSUB:
codec_id = CODEC_ID_DVB_SUBTITLE; codec_id = CODEC_ID_DVB_SUBTITLE;
break; break;
@ -125,6 +128,9 @@ codec_id2streaming_component_type(enum CodecID id)
case CODEC_ID_MP2: case CODEC_ID_MP2:
type = SCT_MPEG2AUDIO; type = SCT_MPEG2AUDIO;
break; break;
case CODEC_ID_VORBIS:
type = SCT_VORBIS;
break;
case CODEC_ID_DVB_SUBTITLE: case CODEC_ID_DVB_SUBTITLE:
type = SCT_DVBSUB; type = SCT_DVBSUB;
break; break;

View file

@ -65,6 +65,19 @@ ebml_append_size(htsbuf_queue_t *q, uint32_t size)
} }
void
ebml_append_xiph_size(htsbuf_queue_t *q, int size)
{
int i;
uint8_t u8[4] = {0xff, size % 0xff};
for(i=0; i<size/0xff; i++)
htsbuf_append(q, u8, 1);
return htsbuf_append(q, u8+1, 1);
}
void void
ebml_append_bin(htsbuf_queue_t *q, unsigned id, const void *data, size_t len) ebml_append_bin(htsbuf_queue_t *q, unsigned id, const void *data, size_t len)
{ {

View file

@ -7,6 +7,8 @@ void ebml_append_id(htsbuf_queue_t *q, uint32_t id);
void ebml_append_size(htsbuf_queue_t *q, uint32_t size); void ebml_append_size(htsbuf_queue_t *q, uint32_t size);
void ebml_append_xiph_size(htsbuf_queue_t *q, int size);
void ebml_append_bin(htsbuf_queue_t *q, unsigned id, void ebml_append_bin(htsbuf_queue_t *q, unsigned id,
const void *data, size_t len); const void *data, size_t len);

View file

@ -25,6 +25,7 @@
#include <unistd.h> #include <unistd.h>
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include <limits.h>
#include "tvheadend.h" #include "tvheadend.h"
#include "streaming.h" #include "streaming.h"
@ -157,6 +158,39 @@ getuuid(char *id)
} }
/**
*
*/
static int
mk_split_vorbis_headers(uint8_t *extradata, int extradata_size,
uint8_t *header_start[3], int header_len[3])
{
int i;
if (extradata_size >= 3 && extradata_size < INT_MAX - 0x1ff && extradata[0] == 2) {
int overall_len = 3;
extradata++;
for (i=0; i<2; i++, extradata++) {
header_len[i] = 0;
for (; overall_len < extradata_size && *extradata==0xff; extradata++) {
header_len[i] += 0xff;
overall_len += 0xff + 1;
}
header_len[i] += *extradata;
overall_len += *extradata;
if (overall_len > extradata_size)
return -1;
}
header_len[2] = extradata_size - overall_len;
header_start[0] = extradata;
header_start[1] = header_start[0] + header_len[0];
header_start[2] = header_start[1] + header_len[1];
} else {
return -1;
}
return 0;
}
/** /**
* *
*/ */
@ -253,6 +287,11 @@ mk_build_tracks(mk_mux_t *mkm, const streaming_start_t *ss)
codec_id = "A_AAC"; codec_id = "A_AAC";
break; break;
case SCT_VORBIS:
tracktype = 2;
codec_id = "A_VORBIS";
break;
case SCT_DVBSUB: case SCT_DVBSUB:
tracktype = 0x11; tracktype = 0x11;
codec_id = "S_DVBSUB"; codec_id = "S_DVBSUB";
@ -294,6 +333,32 @@ mk_build_tracks(mk_mux_t *mkm, const streaming_start_t *ss)
pktbuf_len(ssc->ssc_gh)); pktbuf_len(ssc->ssc_gh));
break; break;
case SCT_VORBIS:
if(ssc->ssc_gh) {
htsbuf_queue_t *cp;
uint8_t *header_start[3];
int header_len[3];
int j;
if(mk_split_vorbis_headers(pktbuf_ptr(ssc->ssc_gh),
pktbuf_len(ssc->ssc_gh),
header_start,
header_len) < 0)
break;
cp = htsbuf_queue_alloc(0);
ebml_append_xiph_size(cp, 2);
for (j = 0; j < 2; j++)
ebml_append_xiph_size(cp, header_len[j]);
for (j = 0; j < 3; j++)
htsbuf_append(cp, header_start[j], header_len[j]);
ebml_append_master(t, 0x63a2, cp);
}
break;
case SCT_DVBSUB: case SCT_DVBSUB:
buf4[0] = ssc->ssc_composition_id >> 8; buf4[0] = ssc->ssc_composition_id >> 8;
buf4[1] = ssc->ssc_composition_id; buf4[1] = ssc->ssc_composition_id;

View file

@ -91,6 +91,7 @@ apply_header(streaming_start_component_t *ssc, th_pkt_t *pkt)
case SCT_H264: case SCT_H264:
case SCT_MPEG2VIDEO: case SCT_MPEG2VIDEO:
case SCT_VORBIS:
if(pkt->pkt_header != NULL) { if(pkt->pkt_header != NULL) {
ssc->ssc_gh = pkt->pkt_header; ssc->ssc_gh = pkt->pkt_header;
@ -124,7 +125,8 @@ header_complete(streaming_start_component_t *ssc, int not_so_picky)
(ssc->ssc_type == SCT_H264 || (ssc->ssc_type == SCT_H264 ||
ssc->ssc_type == SCT_MPEG2VIDEO || ssc->ssc_type == SCT_MPEG2VIDEO ||
ssc->ssc_type == SCT_MP4A || ssc->ssc_type == SCT_MP4A ||
ssc->ssc_type == SCT_AAC)) ssc->ssc_type == SCT_AAC ||
ssc->ssc_type == SCT_VORBIS))
return 0; return 0;
return 1; return 1;
} }

View file

@ -108,7 +108,7 @@ typedef struct transcoder {
#define WORKING_ENCODER(x) (x == CODEC_ID_H264 || x == CODEC_ID_MPEG2VIDEO || \ #define WORKING_ENCODER(x) (x == CODEC_ID_H264 || x == CODEC_ID_MPEG2VIDEO || \
x == CODEC_ID_VP8 || x == CODEC_ID_AAC || \ x == CODEC_ID_VP8 || x == CODEC_ID_AAC || \
x == CODEC_ID_MP2) x == CODEC_ID_MP2 || x == CODEC_ID_VORBIS)
uint32_t transcoding_enabled = 0; uint32_t transcoding_enabled = 0;
@ -375,6 +375,13 @@ transcoder_stream_audio(transcoder_stream_t *ts, th_pkt_t *pkt)
octx->flags |= CODEC_FLAG_QSCALE; octx->flags |= CODEC_FLAG_QSCALE;
break; break;
case SCT_VORBIS:
octx->flags |= CODEC_FLAG_QSCALE;
octx->flags |= CODEC_FLAG_GLOBAL_HEADER;
octx->channels = 2; // Only stereo suported by libavcodec
octx->global_quality = 4*FF_QP2LAMBDA;
break;
default: default:
break; break;
} }

View file

@ -946,6 +946,7 @@ static struct strtab streamtypetab[] = {
{ "EAC3", SCT_EAC3 }, { "EAC3", SCT_EAC3 },
{ "AAC", SCT_MP4A }, { "AAC", SCT_MP4A },
{ "VP8", SCT_VP8 }, { "VP8", SCT_VP8 },
{ "VORBIS", SCT_VORBIS },
}; };

View file

@ -200,14 +200,16 @@ typedef enum {
SCT_EAC3, SCT_EAC3,
SCT_MP4A, SCT_MP4A,
SCT_VP8, SCT_VP8,
SCT_VORBIS,
} streaming_component_type_t; } streaming_component_type_t;
#define SCT_ISVIDEO(t) ((t) == SCT_MPEG2VIDEO || (t) == SCT_H264 || \ #define SCT_ISVIDEO(t) ((t) == SCT_MPEG2VIDEO || (t) == SCT_H264 || \
(t) == SCT_VP8) (t) == SCT_VP8)
#define SCT_ISAUDIO(t) ((t) == SCT_MPEG2AUDIO || (t) == SCT_AC3 || \ #define SCT_ISAUDIO(t) ((t) == SCT_MPEG2AUDIO || (t) == SCT_AC3 || \
(t) == SCT_AAC || (t) == SCT_MP4A || \ (t) == SCT_AAC || (t) == SCT_MP4A || \
(t) == SCT_EAC3) (t) == SCT_EAC3 || (t) == SCT_VORBIS)
#define SCT_ISSUBTITLE(t) ((t) == SCT_TEXTSUB || (t) == SCT_DVBSUB) #define SCT_ISSUBTITLE(t) ((t) == SCT_TEXTSUB || (t) == SCT_DVBSUB)
/** /**