Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
muxers: mkv/libav add HEVC support
  • Loading branch information
perexg committed Sep 18, 2015
1 parent c44cc22 commit b8219cf
Show file tree
Hide file tree
Showing 10 changed files with 1,294 additions and 56 deletions.
1 change: 1 addition & 0 deletions Makefile
Expand Up @@ -218,6 +218,7 @@ SRCS-2 += \
src/parsers/parsers.c \
src/parsers/bitstream.c \
src/parsers/parser_h264.c \
src/parsers/parser_hevc.c \
src/parsers/parser_latm.c \
src/parsers/parser_avc.c \
src/parsers/parser_teletext.c \
Expand Down
11 changes: 8 additions & 3 deletions src/muxer/muxer_libav.c
Expand Up @@ -34,6 +34,7 @@ typedef struct lav_muxer {
muxer_t;
AVFormatContext *lm_oc;
AVBitStreamFilterContext *lm_h264_filter;
AVBitStreamFilterContext *lm_hevc_filter;
int lm_fd;
int lm_init;
} lav_muxer_t;
Expand Down Expand Up @@ -273,8 +274,10 @@ lav_muxer_init(muxer_t* m, const struct streaming_start *ss, const char *name)
av_dict_set(&oc->metadata, "service_name", name, 0);
av_dict_set(&oc->metadata, "service_provider", app, 0);

if(lm->m_config.m_type == MC_MPEGTS)
if(lm->m_config.m_type == MC_MPEGTS) {
lm->lm_h264_filter = av_bitstream_filter_init("h264_mp4toannexb");
lm->lm_hevc_filter = av_bitstream_filter_init("hevc_mp4toannexb");
}

oc->max_delay = 0.7 * AV_TIME_BASE;

Expand Down Expand Up @@ -419,10 +422,12 @@ lav_muxer_write_pkt(muxer_t *m, streaming_message_type_t smt, void *data)
tofree = NULL;
av_init_packet(&packet);

if(lm->lm_h264_filter && st->codec->codec_id == AV_CODEC_ID_H264) {
if((lm->lm_h264_filter && st->codec->codec_id == AV_CODEC_ID_H264) ||
(lm->lm_hevc_filter && st->codec->codec_id == AV_CODEC_ID_HEVC)) {
pkt = avc_convert_pkt(opkt = pkt);
pkt_ref_dec(opkt);
if(av_bitstream_filter_filter(lm->lm_h264_filter,
if(av_bitstream_filter_filter(st->codec->codec_id == AV_CODEC_ID_H264 ?
lm->lm_h264_filter : lm->lm_hevc_filter,
st->codec,
NULL,
&packet.data,
Expand Down
15 changes: 11 additions & 4 deletions src/muxer/tvh/mkmux.c
Expand Up @@ -34,6 +34,7 @@
#include "ebml.h"
#include "lang_codes.h"
#include "parsers/parser_avc.h"
#include "parsers/parser_hevc.h"

extern int dvr_iov_max;

Expand All @@ -49,6 +50,7 @@ TAILQ_HEAD(mk_chapter_queue, mk_chapter);
typedef struct mk_track {
int index;
int avc;
int hevc;
int type;
int tracknum;
int tracktype;
Expand Down Expand Up @@ -279,6 +281,12 @@ mk_build_tracks(mk_mux_t *mkm, const streaming_start_t *ss)
tr->avc = 1;
break;

case SCT_HEVC:
tracktype = 1;
codec_id = "V_MPEGH/ISO/HEVC";
tr->hevc = 1;
break;

case SCT_VP8:
tracktype = 1;
codec_id = "V_VP8";
Expand All @@ -289,10 +297,6 @@ mk_build_tracks(mk_mux_t *mkm, const streaming_start_t *ss)
codec_id = "V_VP9";
break;

case SCT_HEVC:
tvherror("mkv", "HEVC (H265) codec is not suppored for Matroska muxer (work in progress)");
continue;

case SCT_MPEG2AUDIO:
tracktype = 2;
codec_id = "A_MPEG/L2";
Expand Down Expand Up @@ -361,6 +365,9 @@ mk_build_tracks(mk_mux_t *mkm, const streaming_start_t *ss)
if (tr->avc) {
isom_write_avcc(&hdr, pktbuf_ptr(ssc->ssc_gh),
pktbuf_len(ssc->ssc_gh));
} else if (tr->hevc) {
isom_write_hvcc(&hdr, pktbuf_ptr(ssc->ssc_gh),
pktbuf_len(ssc->ssc_gh));
} else {
sbuf_append(&hdr, pktbuf_ptr(ssc->ssc_gh),
pktbuf_len(ssc->ssc_gh));
Expand Down
52 changes: 37 additions & 15 deletions src/parsers/bitstream.c
Expand Up @@ -21,29 +21,50 @@
#include "bitstream.h"


void
init_rbits(bitstream_t *bs, const uint8_t *data, int bits)
int
init_rbits(bitstream_t *bs, const uint8_t *data, uint32_t bits)
{
bs->wdata = NULL;
bs->rdata = data;
bs->offset = 0;
bs->len = bits;
return 0;
}


void
init_wbits(bitstream_t *bs, uint8_t *data, int bits)
int
init_wbits(bitstream_t *bs, uint8_t *data, uint32_t bits)
{
bs->wdata = data;
bs->rdata = NULL;
bs->offset = 0;
bs->len = bits;
return 0;
}

uint32_t
read_bits(bitstream_t *bs, uint32_t num)
{
uint32_t r = 0;

while(num > 0) {
if(bs->offset >= bs->len)
return 0;

num--;

if(bs->rdata[bs->offset / 8] & (1 << (7 - (bs->offset & 7))))
r |= 1 << num;

bs->offset++;
}
return r;
}

unsigned int
read_bits(bitstream_t *bs, int num)
uint64_t
read_bits64(bitstream_t *bs, uint32_t num)
{
unsigned int r = 0;
uint64_t r = 0;

while(num > 0) {
if(bs->offset >= bs->len)
Expand All @@ -59,10 +80,10 @@ read_bits(bitstream_t *bs, int num)
return r;
}

unsigned int
show_bits(bitstream_t *bs, int num)
uint32_t
show_bits(bitstream_t *bs, uint32_t num)
{
unsigned int r = 0, offset = bs->offset;
uint32_t r = 0, offset = bs->offset;

while(num > 0) {
if(offset >= bs->len)
Expand All @@ -78,10 +99,11 @@ show_bits(bitstream_t *bs, int num)
return r;
}

unsigned int
uint32_t
read_golomb_ue(bitstream_t *bs)
{
int b, lzb = -1;
uint32_t b;
int lzb = -1;

for(b = 0; !b && !bs_eof(bs); lzb++)
b = read_bits1(bs);
Expand All @@ -92,10 +114,10 @@ read_golomb_ue(bitstream_t *bs)
}


signed int
int32_t
read_golomb_se(bitstream_t *bs)
{
int v, pos;
uint32_t v, pos;
v = read_golomb_ue(bs);
if(v == 0)
return 0;
Expand All @@ -107,7 +129,7 @@ read_golomb_se(bitstream_t *bs)


void
put_bits(bitstream_t *bs, int val, int num)
put_bits(bitstream_t *bs, uint32_t val, uint32_t num)
{
while(num > 0) {
if(bs->offset >= bs->len)
Expand Down
35 changes: 26 additions & 9 deletions src/parsers/bitstream.h
Expand Up @@ -22,20 +22,25 @@
typedef struct bitstream {
const uint8_t *rdata;
uint8_t *wdata;
int offset;
int len;
uint32_t offset;
uint32_t len;
} bitstream_t;

static inline void skip_bits(bitstream_t *bs, int num)
static inline void skip_bits(bitstream_t *bs, uint32_t num)
{ bs->offset += num; }

void init_rbits(bitstream_t *bs, const uint8_t *data, int bits);
static inline void skip_bits1(bitstream_t *bs)
{ bs->offset++; }

void init_wbits(bitstream_t *bs, uint8_t *data, int bits);
int init_rbits(bitstream_t *bs, const uint8_t *data, uint32_t bits);

unsigned int read_bits(bitstream_t *gb, int num);
int init_wbits(bitstream_t *bs, uint8_t *data, uint32_t bits);

unsigned int show_bits(bitstream_t *gb, int num);
uint32_t read_bits(bitstream_t *gb, uint32_t num);

uint64_t read_bits64(bitstream_t *gb, uint32_t num);

uint32_t show_bits(bitstream_t *gb, uint32_t num);

static inline unsigned int read_bits1(bitstream_t *gb)
{ return read_bits(gb, 1); }
Expand All @@ -44,12 +49,24 @@ unsigned int read_golomb_ue(bitstream_t *gb);

signed int read_golomb_se(bitstream_t *gb);

static inline unsigned int remaining_bits(bitstream_t *gb)
static inline uint32_t remaining_bits(bitstream_t *gb)
{ return gb->len - gb->offset; }

void put_bits(bitstream_t *bs, int val, int num);
void put_bits(bitstream_t *bs, uint32_t val, uint32_t num);

static inline int bs_eof(const bitstream_t *bs)
{ return bs->offset >= bs->len; }

static inline uint32_t
RB32(const uint8_t *d)
{
return (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3];
}

static inline uint32_t
RB24(const uint8_t *d)
{
return (d[0] << 16) | (d[1] << 8) | d[2];
}

#endif /* BITSTREAM_H_ */
23 changes: 5 additions & 18 deletions src/parsers/parser_avc.c
Expand Up @@ -20,6 +20,8 @@
*/

#include "parser_avc.h"
#include "bitstream.h"

static const uint8_t *
avc_find_startcode_internal(const uint8_t *p, const uint8_t *end)
{
Expand Down Expand Up @@ -66,7 +68,7 @@ avc_find_startcode(const uint8_t *p, const uint8_t *end)
return out;
}

static int avc_parse_nal_units(sbuf_t *sb, const uint8_t *buf_in, int size)
int avc_parse_nal_units(sbuf_t *sb, const uint8_t *buf_in, int size)
{
const uint8_t *p = buf_in;
const uint8_t *end = p + size;
Expand All @@ -91,7 +93,7 @@ static int avc_parse_nal_units(sbuf_t *sb, const uint8_t *buf_in, int size)
return size;
}

static int
int
avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size)
{
sbuf_t sb;
Expand All @@ -105,21 +107,6 @@ avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size)
return 0;
}


static inline uint32_t
RB32(const uint8_t *d)
{
return (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3];
}

static inline uint32_t
RB24(const uint8_t *d)
{
return (d[0] << 16) | (d[1] << 8) | d[2];
}

#define FFMIN(a, b) ((a) > (b) ? (b) : (a))

int
isom_write_avcc(sbuf_t *sb, const uint8_t *data, int len)
{
Expand All @@ -143,7 +130,7 @@ isom_write_avcc(sbuf_t *sb, const uint8_t *data, int len)
while (end - buf > 4) {
unsigned int size;
uint8_t nal_type;
size = FFMIN(RB32(buf), end - buf - 4);
size = MIN(RB32(buf), end - buf - 4);
buf += 4;
nal_type = buf[0] & 0x1f;

Expand Down
4 changes: 4 additions & 0 deletions src/parsers/parser_avc.h
Expand Up @@ -25,6 +25,10 @@
#include "tvheadend.h"
#include "packet.h"

int avc_parse_nal_units(sbuf_t *sb, const uint8_t *buf_in, int size);

int avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size);

int isom_write_avcc(sbuf_t *sb, const uint8_t *src, int len);

th_pkt_t *avc_convert_pkt(th_pkt_t *src);
Expand Down

0 comments on commit b8219cf

Please sign in to comment.