[mythtv] [patch] pmt tracking bugfix
Daniel Thor Kristjansson
danielk at mrl.nyu.edu
Sat Nov 13 18:58:33 UTC 2004
This patch fixes a bug in the PMT tracking code for MPEG-TS streams.
This patch delays the call to avformatdecoder's HandleStreamChange()
until the stream is fully initialized.
-- Daniel
-------------- next part --------------
Index: libs/libavformat/utils.c
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libavformat/utils.c,v
retrieving revision 1.26
diff -u -r1.26 utils.c
--- libs/libavformat/utils.c 22 Oct 2004 09:56:15 -0000 1.26
+++ libs/libavformat/utils.c 13 Nov 2004 18:49:20 -0000
@@ -1817,17 +1817,36 @@
*/
AVStream *av_new_stream(AVFormatContext *s, int id)
{
- AVStream *st;
+ AVStream *st = av_mallocz(sizeof(AVStream));
+ if (st) {
+ avcodec_get_context_defaults(&st->codec);
+ AVStream *stream = av_add_stream(s, st, id);
+ if (!stream)
+ av_free(st);
+ return stream;
+ }
+ return NULL;
+}
+
+/**
+ * Add a stream to an MPEG media stream. This is used by mpegts
+ * instead of av_new_stream, so we can track new streams
+ * as indicated by the PMT.
+ *
+ * @param s MPEG media stream handle
+ * @param st new media stream
+ * @param id file format dependent stream id
+ */
+AVStream *av_add_stream(AVFormatContext *s, AVStream *st, int id)
+{
+ if (!st)
+ return NULL;
av_remove_stream(s, id);
if (s->nb_streams >= MAX_STREAMS)
return NULL;
- st = av_mallocz(sizeof(AVStream));
- if (!st)
- return NULL;
- avcodec_get_context_defaults(&st->codec);
if (s->iformat) {
/* no default bitrate if decoding */
st->codec.bit_rate = 0;
@@ -1843,27 +1862,28 @@
st->last_IP_pts = AV_NOPTS_VALUE;
s->streams[s->nb_streams++] = st;
- if (s->streams_changed)
- s->streams_changed(s->stream_change_data);
return st;
}
+/**
+ * Remove a stream from a media stream. This is used by mpegts,
+ * so we can track streams as indicated by the PMT.
+ *
+ * @param s MPEG media stream handle
+ * @param id stream id of stream to remove
+ */
void av_remove_stream(AVFormatContext *s, int id) {
- //printf("av_remove_stream 0x%x -- IGNORED \n", id);
- //return; // TODO HACK
int i;
for (i=0; i<s->nb_streams; i++)
- if (s->streams[i]->id == id) {
- printf("av_remove_stream 0x%x\n", id);
- s->nb_streams--;
- if (s->nb_streams-i>0)
- memmove(&s->streams[i], &s->streams[i+1], (s->nb_streams-i)*sizeof(AVFormatContext *));
- if (s->streams_changed)
- s->streams_changed(s->stream_change_data);
- continue;
- }
+ if (s->streams[i]->id == id) {
+ printf("av_remove_stream 0x%x\n", id);
+ s->nb_streams--;
+ if (s->nb_streams-i>0)
+ memmove(&s->streams[i], &s->streams[i+1], (s->nb_streams-i)*sizeof(AVFormatContext *));
+ continue;
+ }
for (i=0; i<s->nb_streams; i++)
- s->streams[i]->index=i;
+ s->streams[i]->index=i;
}
/************************************************************/
Index: libs/libavformat/mpegts.c
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libavformat/mpegts.c,v
retrieving revision 1.21
diff -u -r1.21 mpegts.c
--- libs/libavformat/mpegts.c 23 Oct 2004 12:04:58 -0000 1.21
+++ libs/libavformat/mpegts.c 13 Nov 2004 18:49:20 -0000
@@ -399,6 +399,7 @@
SectionHeader h1, *h = &h1;
const uint8_t *p, *p_end;
int program_info_length, pcr_pid, pid, stream_type, desc_length;
+ int changes = 0;
#ifdef DEBUG_SI
printf("PMT:\n");
@@ -467,6 +468,7 @@
if (!pmtInList(ts->pmt_pids_old, pid)) {
printf("adding pes stream at pid 0x%x with type %i\n", pid, stream_type);
add_pes_stream(ts, pid, stream_type);
+ changes = 1;
}
ts->pmt_pids[i]=pid; i++;
break;
@@ -482,6 +484,7 @@
printf("closing filter for pid 0x%x\n", ts->pmt_pids_old[i]);
av_remove_stream(ts->stream, ts->pmt_pids_old[i]);
mpegts_close_filter(ts, ts->pids[ts->pmt_pids_old[i]]);
+ changes = 1;
}
memcpy(ts->pmt_pids_old, ts->pmt_pids, PMT_PIDS_MAX*sizeof(int));
@@ -491,6 +494,13 @@
ts->set_service_cb(ts->set_service_opaque, 0);
mpegts_close_filter(ts, ts->pmt_filter);
ts->pmt_filter = NULL;
+
+ /* notify stream_changed listeners */
+ AVFormatContext *s = ts->stream;
+ if (changes && s->streams_changed) {
+ printf("streams_changed()\n");
+ s->streams_changed(s->stream_change_data);
+ }
}
static void pat_cb(void *opaque, const uint8_t *section, int section_len)
@@ -791,14 +801,17 @@
av_set_pts_info(st, 60, 1, 90000);
}
-static void create_stream(PESContext *pes, int code)
+static int create_stream(PESContext *pes, int code)
{
- pes->st = av_new_stream(pes->stream, pes->pid);
- if (pes->st) {
- init_stream(pes->st, pes->stream_type, code);
- pes->st->priv_data = pes;
- pes->st->need_parsing = 1;
- }
+ CHECKED_ALLOCZ(pes->st, sizeof(AVStream));
+ avcodec_get_context_defaults(&pes->st->codec); // sets codec defaults
+ init_stream(pes->st, pes->stream_type, code); // sets codec type and id
+ pes->st->priv_data = pes;
+ pes->st->need_parsing = 1;
+
+ pes->st = av_add_stream(pes->stream, pes->st, pes->pid);
+fail: //for the CHECKED_ALLOCZ macro
+ return (pes->st)? 0 : -1;
}
@@ -842,8 +855,10 @@
(code >= 0x1e0 && code <= 0x1ef) ||
(code == 0x1bd)))
goto skip;
- if (!pes->st)
- create_stream(pes, code);
+ if (!pes->st && -1==create_stream(pes, code)) {
+ av_log(NULL, AV_LOG_ERROR, "Error: create_stream() failed in mpegts_push_data");
+ goto skip;
+ }
pes->state = MPEGTS_PESHEADER_FILL;
pes->total_size = (pes->header[4] << 8) | pes->header[5];
/* NOTE: a zero total size means the PES size is
@@ -938,8 +953,10 @@
}
/* create a PES context */
- if (!(pes=av_mallocz(sizeof(PESContext))))
+ if (!(pes=av_mallocz(sizeof(PESContext)))) {
+ av_log(NULL, AV_LOG_ERROR, "Error: av_mallocz() failed in add_pes_stream");
return -1;
+ }
pes->ts = ts;
pes->stream = ts->stream;
pes->pid = pid;
@@ -947,10 +964,17 @@
tss = mpegts_open_pes_filter(ts, pid, mpegts_push_data, pes);
if (!tss) {
av_free(pes);
+ av_log(NULL, AV_LOG_ERROR, "Error: unable to open mpegts PES filter in add_pes_stream");
+ return -1;
+ }
+ if (!pes->st && -1==create_stream(pes, -1)) {
+ av_log(NULL, AV_LOG_ERROR, "Error: create_stream() failed in add_pes_stream");
return -1;
}
- if (!pes->st)
- create_stream(pes, -1);
+
+ assert(pes->stream_type==stream_type);
+ assert(pes->st->codec.codec_type);
+ assert(pes->st->codec.codec_id);
return 0;
}
Index: libs/libavformat/avformat.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libavformat/avformat.h,v
retrieving revision 1.24
diff -u -r1.24 avformat.h
--- libs/libavformat/avformat.h 22 Oct 2004 09:56:15 -0000 1.24
+++ libs/libavformat/avformat.h 13 Nov 2004 18:49:21 -0000
@@ -558,6 +558,7 @@
int av_read_pause(AVFormatContext *s);
void av_close_input_file(AVFormatContext *s);
AVStream *av_new_stream(AVFormatContext *s, int id);
+AVStream *av_add_stream(AVFormatContext *s, AVStream *st, int id);
void av_remove_stream(AVFormatContext *s, int id);
void av_set_pts_info(AVStream *s, int pts_wrap_bits,
int pts_num, int pts_den);
More information about the mythtv-dev
mailing list