Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
H264: move avc parsing from globalheaders to mkv mux
  • Loading branch information
perexg committed Nov 19, 2014
1 parent b70fa32 commit bf1c902
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 63 deletions.
64 changes: 41 additions & 23 deletions src/muxer/tvh/mkmux.c
Expand Up @@ -32,6 +32,7 @@
#include "dvr/dvr.h"
#include "mkmux.h"
#include "ebml.h"
#include "parsers/parser_avc.h"

extern int dvr_iov_max;

Expand All @@ -47,6 +48,7 @@ TAILQ_HEAD(mk_chapter_queue, mk_chapter);
typedef struct mk_track {
int index;
int enabled;
int avc;
int type;
int tracknum;
int disabled;
Expand Down Expand Up @@ -236,26 +238,28 @@ mk_build_tracks(mk_mux_t *mkm, const streaming_start_t *ss)
int tracknum = 0;
uint8_t buf4[4];
uint32_t bit_depth = 0;
mk_track_t *tr;

mkm->tracks = calloc(1, sizeof(mk_track_t) * ss->ss_num_components);
mkm->ntracks = ss->ss_num_components;

for(i = 0; i < ss->ss_num_components; i++) {
ssc = &ss->ss_components[i];
tr = &mkm->tracks[i];

mkm->tracks[i].disabled = ssc->ssc_disabled;
tr->disabled = ssc->ssc_disabled;

if(ssc->ssc_disabled)
continue;

mkm->tracks[i].index = ssc->ssc_index;
mkm->tracks[i].type = ssc->ssc_type;
mkm->tracks[i].channels = ssc->ssc_channels;
mkm->tracks[i].aspect_num = ssc->ssc_aspect_num;
mkm->tracks[i].aspect_den = ssc->ssc_aspect_den;
mkm->tracks[i].commercial = COMMERCIAL_UNKNOWN;
mkm->tracks[i].sri = ssc->ssc_sri;
mkm->tracks[i].nextpts = PTS_UNSET;
tr->index = ssc->ssc_index;
tr->type = ssc->ssc_type;
tr->channels = ssc->ssc_channels;
tr->aspect_num = ssc->ssc_aspect_num;
tr->aspect_den = ssc->ssc_aspect_den;
tr->commercial = COMMERCIAL_UNKNOWN;
tr->sri = ssc->ssc_sri;
tr->nextpts = PTS_UNSET;

if (mkm->webm && ssc->ssc_type != SCT_VP8 && ssc->ssc_type != SCT_VORBIS)
tvhwarn("mkv", "WEBM format supports only VP8+VORBIS streams (detected %s)",
Expand All @@ -270,6 +274,7 @@ mk_build_tracks(mk_mux_t *mkm, const streaming_start_t *ss)
case SCT_H264:
tracktype = 1;
codec_id = "V_MPEG4/ISO/AVC";
tr->avc = 1;
break;

case SCT_VP8:
Expand Down Expand Up @@ -327,15 +332,14 @@ mk_build_tracks(mk_mux_t *mkm, const streaming_start_t *ss)
continue;
}

mkm->tracks[i].enabled = 1;
tracknum++;
mkm->tracks[i].tracknum = tracknum;
tr->enabled = 1;
tr->tracknum = ++tracknum;
mkm->has_video |= (tracktype == 1);

t = htsbuf_queue_alloc(0);

ebml_append_uint(t, 0xd7, mkm->tracks[i].tracknum);
ebml_append_uint(t, 0x73c5, mkm->tracks[i].tracknum);
ebml_append_uint(t, 0xd7, tr->tracknum);
ebml_append_uint(t, 0x73c5, tr->tracknum);
ebml_append_uint(t, 0x83, tracktype);
ebml_append_uint(t, 0x9c, 0); // Lacing
ebml_append_string(t, 0x86, codec_id);
Expand All @@ -348,10 +352,19 @@ mk_build_tracks(mk_mux_t *mkm, const streaming_start_t *ss)
case SCT_MPEG2VIDEO:
case SCT_MP4A:
case SCT_AAC:
if(ssc->ssc_gh)
ebml_append_bin(t, 0x63a2,
pktbuf_ptr(ssc->ssc_gh),
pktbuf_len(ssc->ssc_gh));
if(ssc->ssc_gh) {
sbuf_t hdr;
sbuf_init(&hdr);
if (tr->avc) {
isom_write_avcc(&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));
}
ebml_append_bin(t, 0x63a2, hdr.sb_data, hdr.sb_ptr);
sbuf_free(&hdr);
}
break;

case SCT_VORBIS:
Expand Down Expand Up @@ -1138,12 +1151,12 @@ mk_mux_write_pkt(mk_mux_t *mkm, th_pkt_t *pkt)
{
int i, mark;
mk_track_t *t = NULL;
for(i = 0; i < mkm->ntracks;i++) {
if(mkm->tracks[i].index == pkt->pkt_componentindex &&
mkm->tracks[i].enabled) {
t = &mkm->tracks[i];
th_pkt_t *opkt;

for (i = 0; i < mkm->ntracks; i++) {
t = &mkm->tracks[i];
if (t->index == pkt->pkt_componentindex && t->enabled)
break;
}
}

if(t == NULL || t->disabled) {
Expand Down Expand Up @@ -1181,6 +1194,11 @@ mk_mux_write_pkt(mk_mux_t *mkm, th_pkt_t *pkt)
if(mark)
mk_mux_insert_chapter(mkm);

if(t->avc) {
pkt = avc_convert_pkt(opkt = pkt);
pkt_ref_dec(opkt);
}

mk_write_frame_i(mkm, t, pkt);

pkt_ref_dec(pkt);
Expand Down
2 changes: 1 addition & 1 deletion src/parsers/parser_avc.c
Expand Up @@ -120,7 +120,7 @@ RB24(const uint8_t *d)

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

static int
int
isom_write_avcc(sbuf_t *sb, const uint8_t *data, int len)
{
if (len > 6) {
Expand Down
2 changes: 2 additions & 0 deletions src/parsers/parser_avc.h
Expand Up @@ -25,6 +25,8 @@
#include "tvheadend.h"
#include "packet.h"

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

th_pkt_t *avc_convert_pkt(th_pkt_t *src);

#endif
41 changes: 2 additions & 39 deletions src/plumbing/globalheaders.c
Expand Up @@ -20,7 +20,6 @@
#include "tvheadend.h"
#include "streaming.h"
#include "globalheaders.h"
#include "parsers/parser_avc.h"

typedef struct globalheaders {
streaming_target_t gh_input;
Expand Down Expand Up @@ -152,32 +151,6 @@ headers_complete(globalheaders_t *gh, int64_t qd)
}



/**
*
*/
static th_pkt_t *
convertpkt(streaming_start_component_t *ssc, th_pkt_t *pkt, int hold)
{
th_pkt_t *r;

switch(ssc->ssc_type) {
case SCT_H264:
r = avc_convert_pkt(pkt);
if (!hold)
pkt_ref_dec(pkt);
break;

default:
r = pkt;
if (hold)
pkt_ref_inc(r);
break;
}
return r;
}


/**
*
*/
Expand Down Expand Up @@ -214,7 +187,7 @@ gh_hold(globalheaders_t *gh, streaming_message_t *sm)
break;
}

pkt = convertpkt(ssc, pkt, 1);
pkt_ref_inc(pkt);

apply_header(ssc, pkt);

Expand Down Expand Up @@ -273,9 +246,6 @@ gh_hold(globalheaders_t *gh, streaming_message_t *sm)
static void
gh_pass(globalheaders_t *gh, streaming_message_t *sm)
{
th_pkt_t *pkt;
streaming_start_component_t *ssc;

switch(sm->sm_type) {
case SMT_START:
/* stop */
Expand All @@ -295,20 +265,13 @@ gh_pass(globalheaders_t *gh, streaming_message_t *sm)
case SMT_SERVICE_STATUS:
case SMT_SIGNAL_STATUS:
case SMT_NOSTART:
case SMT_PACKET:
case SMT_MPEGTS:
case SMT_SKIP:
case SMT_SPEED:
case SMT_TIMESHIFT_STATUS:
streaming_target_deliver2(gh->gh_output, sm);
break;

case SMT_PACKET:
pkt = sm->sm_data;
ssc = streaming_start_component_find_by_index(gh->gh_ss,
pkt->pkt_componentindex);
sm->sm_data = convertpkt(ssc, pkt, 0);
streaming_target_deliver2(gh->gh_output, sm);
break;
}
}

Expand Down

5 comments on commit bf1c902

@ksooo
Copy link
Contributor

@ksooo ksooo commented on bf1c902 Nov 24, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit introduces https://tvheadend.org/issues/2497 !

@EricV
Copy link
Contributor

@EricV EricV commented on bf1c902 Nov 25, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This kind of bug change and the bug introduced makes me wonder if it will ever stabilize. Running mkvalidator shows the recording are definitively broken and probably haven't been tested.

@ksooo
Copy link
Contributor

@ksooo ksooo commented on bf1c902 Nov 25, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@perexg mkvalidator since this commit complains about "usage of unknown track #0" and you did some modifications to src/muxer/tvh/mkmux.c, function mk_build_tracks() and mk_mux_write_pkt() in this commit. Could this changes probably be related to the broken mkvs?

@EricV
Copy link
Contributor

@EricV EricV commented on bf1c902 Nov 26, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ksooo Maybe you should dump the original TS data (rtpdump, dvdbscan, ...) and provide it so that perexg can try to see where the problem lies?

@perexg
Copy link
Contributor Author

@perexg perexg commented on bf1c902 Nov 26, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the channels are encrypted, it's better to save the service stream in TS (profile pass) format, but I think that commit 39a4db4 should fix this issue.

Please sign in to comment.