redbutton-devel Mailing List for RedButton MHEG Engine (Page 26)
Brought to you by:
skilvington
You can subscribe to this list here.
| 2006 |
Jan
(1) |
Feb
(4) |
Mar
(27) |
Apr
(6) |
May
(46) |
Jun
(45) |
Jul
(7) |
Aug
(4) |
Sep
(7) |
Oct
(5) |
Nov
(10) |
Dec
(11) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2007 |
Jan
(49) |
Feb
(29) |
Mar
(35) |
Apr
(43) |
May
(23) |
Jun
(4) |
Jul
(1) |
Aug
(58) |
Sep
(66) |
Oct
(27) |
Nov
(15) |
Dec
(1) |
| 2008 |
Jan
(11) |
Feb
|
Mar
(8) |
Apr
|
May
|
Jun
(30) |
Jul
(1) |
Aug
(1) |
Sep
(1) |
Oct
|
Nov
(3) |
Dec
(6) |
| 2009 |
Jan
(6) |
Feb
(1) |
Mar
(2) |
Apr
(5) |
May
(2) |
Jun
(1) |
Jul
(7) |
Aug
|
Sep
(2) |
Oct
(2) |
Nov
|
Dec
(6) |
| 2010 |
Jan
(6) |
Feb
|
Mar
(4) |
Apr
|
May
|
Jun
|
Jul
|
Aug
(6) |
Sep
(4) |
Oct
|
Nov
(11) |
Dec
(4) |
| 2011 |
Jan
|
Feb
(11) |
Mar
(8) |
Apr
|
May
|
Jun
(3) |
Jul
|
Aug
|
Sep
(4) |
Oct
|
Nov
(2) |
Dec
|
| 2012 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: <ski...@us...> - 2006-05-14 11:29:46
|
Revision: 57 Author: skilvington Date: 2006-05-14 04:29:37 -0700 (Sun, 14 May 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=57&view=rev Log Message: ----------- speed up video overlay Modified Paths: -------------- redbutton-browser/trunk/VideoClass.c Modified: redbutton-browser/trunk/VideoClass.c =================================================================== --- redbutton-browser/trunk/VideoClass.c 2006-05-14 09:56:06 UTC (rev 56) +++ redbutton-browser/trunk/VideoClass.c 2006-05-14 11:29:37 UTC (rev 57) @@ -373,8 +373,10 @@ return; /* draw the video frame onto the Window contents Pixmap */ - if(t->inst.player != NULL) - MHEGStreamPlayer_drawCurrentFrame(t->inst.player); +// need to do the equivalent of this, but not here +// => get rid of VideoClass.inst.player too +// if(t->inst.player != NULL) +// MHEGStreamPlayer_drawCurrentFrame(t->inst.player); /* make a transparent hole in the MHEG overlay so we can see the video below it */ MHEGDisplay_fillTransparentRectangle(d, &ins_pos, &ins_box); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-05-14 09:56:38
|
Revision: 56 Author: skilvington Date: 2006-05-14 02:56:06 -0700 (Sun, 14 May 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=56&view=rev Log Message: ----------- enable video display (too slow to be practical yet) Modified Paths: -------------- redbutton-browser/trunk/MHEGDisplay.c redbutton-browser/trunk/MHEGDisplay.h redbutton-browser/trunk/MHEGStreamPlayer.c redbutton-browser/trunk/MHEGStreamPlayer.h redbutton-browser/trunk/StreamComponent.c redbutton-browser/trunk/TODO redbutton-browser/trunk/VideoClass.c redbutton-browser/trunk/VideoClass.h redbutton-browser/trunk/add_instance_vars.conf Modified: redbutton-browser/trunk/MHEGDisplay.c =================================================================== --- redbutton-browser/trunk/MHEGDisplay.c 2006-05-12 12:46:29 UTC (rev 55) +++ redbutton-browser/trunk/MHEGDisplay.c 2006-05-14 09:56:06 UTC (rev 56) @@ -80,6 +80,7 @@ XGCValues gcvals; XRenderPictFormat *pic_format; XRenderPictureAttributes pa; + Pixmap overlay; Pixmap textfg; /* fake argc, argv for XtDisplayInitialize */ int argc = 0; @@ -216,13 +217,21 @@ wm_delete_window = XInternAtom(d->dpy, "WM_DELETE_WINDOW", False); XSetWMProtocols(d->dpy, d->win, &wm_delete_window, 1); - /* create an XRender Picture to do the drawing on */ + /* + * create an XRender Picture for the Window contents + * we composite the video frame and the MHEG overlay onto this, then copy it onto the Window + */ + pic_format = XRenderFindVisualFormat(d->dpy, d->vis); d->contents = XCreatePixmap(d->dpy, d->win, d->xres, d->yres, d->depth); - pic_format = XRenderFindVisualFormat(d->dpy, d->vis); d->contents_pic = XRenderCreatePicture(d->dpy, d->contents, pic_format, 0, NULL); + /* create a 32-bit XRender Picture to draw the MHEG objects on */ + pic_format = XRenderFindStandardFormat(d->dpy, PictStandardARGB32); + overlay = XCreatePixmap(d->dpy, d->win, d->xres, d->yres, 32); + d->overlay_pic = XRenderCreatePicture(d->dpy, overlay, pic_format, 0, NULL); + /* a 1x1 Picture to hold the text foreground colour */ - textfg = XCreatePixmap(d->dpy, d->win, 1, 1, d->depth); + textfg = XCreatePixmap(d->dpy, d->win, 1, 1, 32); pa.repeat = True; d->textfg_pic = XRenderCreatePicture(d->dpy, textfg, pic_format, CPRepeat, &pa); @@ -360,6 +369,14 @@ w = (box->x_length * d->xres) / MHEG_XRES; h = (box->y_length * d->yres) / MHEG_YRES; + /* + * if video is being displayed, the current frame will already be in d->contents + * (drawn by the video thread or VideoClass_render) + * overlay the MHEG objects onto the video in d->contents + */ + XRenderComposite(d->dpy, PictOpOver, d->overlay_pic, None, d->contents_pic, x, y, x, y, x, y, w, h); + + /* copy the Window contents onto the screen */ XCopyArea(d->dpy, d->contents, d->win, d->win_gc, x, y, w, h, x, y); return; @@ -397,7 +414,7 @@ printf("TODO: LineStyle %d\n", style); /* draw a rectangle */ - XRenderFillRectangle(d->dpy, PictOpOver, d->contents_pic, &rcol, x, y, w, h); + XRenderFillRectangle(d->dpy, PictOpOver, d->overlay_pic, &rcol, x, y, w, h); return; } @@ -434,7 +451,7 @@ printf("TODO: LineStyle %d\n", style); /* draw a rectangle */ - XRenderFillRectangle(d->dpy, PictOpOver, d->contents_pic, &rcol, x, y, w, h); + XRenderFillRectangle(d->dpy, PictOpOver, d->overlay_pic, &rcol, x, y, w, h); return; } @@ -463,12 +480,36 @@ w = (box->x_length * d->xres) / MHEG_XRES; h = (box->y_length * d->yres) / MHEG_YRES; - XRenderFillRectangle(d->dpy, PictOpOver, d->contents_pic, &rcol, x, y, w, h); + XRenderFillRectangle(d->dpy, PictOpOver, d->overlay_pic, &rcol, x, y, w, h); return; } /* + * explicitly make a transparent rectangle in the MHEG overlay + * MHEGDisplay_fillRectangle() uses PictOpOver => it can't create a transparent box in the output + * this uses PictOpSrc + */ + +void +MHEGDisplay_fillTransparentRectangle(MHEGDisplay *d, XYPosition *pos, OriginalBoxSize *box) +{ + XRenderColor rcol = {0, 0, 0, 0}; + int x, y; + unsigned int w, h; + + /* scale if fullscreen */ + x = (pos->x_position * d->xres) / MHEG_XRES; + y = (pos->y_position * d->yres) / MHEG_YRES; + w = (box->x_length * d->xres) / MHEG_XRES; + h = (box->y_length * d->yres) / MHEG_YRES; + + XRenderFillRectangle(d->dpy, PictOpSrc, d->overlay_pic, &rcol, x, y, w, h); + + return; +} + +/* * coords should be in the range 0-MHEG_XRES, 0-MHEG_YRES */ @@ -494,7 +535,7 @@ dst_x = (dst->x_position * d->xres) / MHEG_XRES; dst_y = (dst->y_position * d->yres) / MHEG_YRES; - XRenderComposite(d->dpy, PictOpOver, bitmap->image_pic, None, d->contents_pic, + XRenderComposite(d->dpy, PictOpOver, bitmap->image_pic, None, d->overlay_pic, src_x, src_y, src_x, src_y, dst_x, dst_y, w, h); @@ -594,7 +635,7 @@ /* round up/down the X coord */ scrn_x = (x * d->xres) / MHEG_XRES; scrn_x = (scrn_x + (face->units_per_EM / 2)) / face->units_per_EM; - XftGlyphRender(d->dpy, PictOpOver, d->textfg_pic, font->font, d->contents_pic, + XftGlyphRender(d->dpy, PictOpOver, d->textfg_pic, font->font, d->overlay_pic, 0, 0, orig_x + scrn_x, y, &glyph, 1); face = XftLockFace(font->font); Modified: redbutton-browser/trunk/MHEGDisplay.h =================================================================== --- redbutton-browser/trunk/MHEGDisplay.h 2006-05-12 12:46:29 UTC (rev 55) +++ redbutton-browser/trunk/MHEGDisplay.h 2006-05-14 09:56:06 UTC (rev 56) @@ -46,7 +46,8 @@ Visual *vis; /* Visual (ie pixel format) used by the Window */ Colormap cmap; /* None, unless we needed to create a Colormap for our Visual */ Pixmap contents; /* current contents of the Window */ - Picture contents_pic; /* XRender wrapper for the contents, this is what we draw on */ + Picture contents_pic; /* XRender wrapper for the contents, this is what we composite on */ + Picture overlay_pic; /* draw MHEG objects on here and overlay it on any video */ Picture textfg_pic; /* 1x1 solid foreground colour for text */ MHEGKeyMapEntry *keymap; /* keyboard mapping */ } MHEGDisplay; @@ -61,6 +62,7 @@ /* drawing routines */ void MHEGDisplay_drawHoriLine(MHEGDisplay *, XYPosition *, unsigned int, int, int, MHEGColour *); void MHEGDisplay_drawVertLine(MHEGDisplay *, XYPosition *, unsigned int, int, int, MHEGColour *); +void MHEGDisplay_fillTransparentRectangle(MHEGDisplay *, XYPosition *, OriginalBoxSize *); void MHEGDisplay_fillRectangle(MHEGDisplay *, XYPosition *, OriginalBoxSize *, MHEGColour *); void MHEGDisplay_drawBitmap(MHEGDisplay *, XYPosition *, OriginalBoxSize *, MHEGBitmap *, XYPosition *); void MHEGDisplay_drawTextElement(MHEGDisplay *, XYPosition *, MHEGFont *, MHEGTextElement *, bool); Modified: redbutton-browser/trunk/MHEGStreamPlayer.c =================================================================== --- redbutton-browser/trunk/MHEGStreamPlayer.c 2006-05-12 12:46:29 UTC (rev 55) +++ redbutton-browser/trunk/MHEGStreamPlayer.c 2006-05-14 09:56:06 UTC (rev 56) @@ -73,6 +73,7 @@ p->videoq = NULL; pthread_mutex_init(&p->current_frame_lock, NULL); + p->current_frame = NULL; return; } @@ -316,6 +317,9 @@ uint8_t *tmpbuf_data = NULL; unsigned int nframes = 0; + if(!p->have_video) + return NULL; + verbose("MHEGStreamPlayer: video thread started"); /* assert */ @@ -454,8 +458,6 @@ pthread_mutex_lock(&p->current_frame_lock); /* convert the next frame to RGB */ img_convert(&rgb_frame, out_format, yuv_frame, vf->pix_fmt, out_width, out_height); -/* TODO */ -/* overlay any MHEG objects above it */ /* we've finished changing the RGB frame now */ pthread_mutex_unlock(&p->current_frame_lock); /* wait until it's time to display the frame */ @@ -480,11 +482,10 @@ last_pts = vf->pts; //now=av_gettime(); //printf("display frame %d: pts=%f this_time=%lld real_time=%lld (diff=%lld)\n", ++nframes, vf->pts, last_time, now, now-last_time); -/* TODO */ -/* take p->video size/position into account */ -/* redraw objects above the video */ -// disable output until we can overlay the MHEG objects -// XShmPutImage(d->dpy, d->win, d->win_gc, p->current_frame, 0, 0, 0, 0, out_width, out_height, False); + /* draw the current frame */ + MHEGStreamPlayer_drawCurrentFrame(p); + /* redraw objects above the video */ + MHEGDisplay_refresh(d, &p->video->inst.Position, &p->video->inst.BoxSize); /* get it drawn straight away */ XFlush(d->dpy); } @@ -500,9 +501,14 @@ safe_free(tmpbuf_data); } + /* get rid of the current frame */ + pthread_mutex_lock(&p->current_frame_lock); /* the XImage data is our shared memory, make sure XDestroyImage doesn't try to free it */ p->current_frame->data = NULL; XDestroyImage(p->current_frame); + /* make sure no-one tries to use it */ + p->current_frame = NULL; + pthread_mutex_unlock(&p->current_frame_lock); XShmDetach(d->dpy, &shm); shmdt(shm.shmaddr); @@ -513,6 +519,34 @@ return NULL; } +void +MHEGStreamPlayer_drawCurrentFrame(MHEGStreamPlayer *p) +{ + MHEGDisplay *d = MHEGEngine_getDisplay(); + int x, y; + unsigned int out_width; + unsigned int out_height; + + pthread_mutex_lock(&p->current_frame_lock); + if(p->current_frame != NULL) + { +/* TODO */ +/* take p->video size/position into account */ +/* remeber fullscreen scaling */ + x = 0; /* origin of p->video */ + y = 0; + out_width = p->current_frame->width; + out_height = p->current_frame->height; + /* draw it onto the Window contents Pixmap */ + XShmPutImage(d->dpy, d->contents, d->win_gc, p->current_frame, 0, 0, x, y, out_width, out_height, False); + /* get it drawn straight away */ + XFlush(d->dpy); + } + pthread_mutex_unlock(&p->current_frame_lock); + + return; +} + /* * usleep(usecs) * need to make sure the other threads get a go while we are sleeping Modified: redbutton-browser/trunk/MHEGStreamPlayer.h =================================================================== --- redbutton-browser/trunk/MHEGStreamPlayer.h 2006-05-12 12:46:29 UTC (rev 55) +++ redbutton-browser/trunk/MHEGStreamPlayer.h 2006-05-14 09:56:06 UTC (rev 56) @@ -33,7 +33,7 @@ void free_VideoFrameListItem(LIST_TYPE(VideoFrame) *); /* player state */ -typedef struct +typedef struct MHEGStreamPlayer { bool playing; /* true when our threads are active */ bool stop; /* true => stop playback */ @@ -64,4 +64,6 @@ void MHEGStreamPlayer_play(MHEGStreamPlayer *); void MHEGStreamPlayer_stop(MHEGStreamPlayer *); +void MHEGStreamPlayer_drawCurrentFrame(MHEGStreamPlayer *); + #endif /* __MHEGSTREAMPLAYER_H__ */ Modified: redbutton-browser/trunk/StreamComponent.c =================================================================== --- redbutton-browser/trunk/StreamComponent.c 2006-05-12 12:46:29 UTC (rev 55) +++ redbutton-browser/trunk/StreamComponent.c 2006-05-14 09:56:06 UTC (rev 56) @@ -109,6 +109,7 @@ break; case StreamComponent_video: + VideoClass_setStreamPlayer(&s->u.video, player); MHEGStreamPlayer_setVideoTag(player, &s->u.video, s->u.video.component_tag); break; @@ -127,6 +128,24 @@ void StreamComponent_stop(StreamComponent *s, MHEGStreamPlayer *player) { + switch(s->choice) + { + case StreamComponent_audio: + break; + + case StreamComponent_video: + VideoClass_setStreamPlayer(&s->u.video, NULL); + break; + + case StreamComponent_rtgraphics: + error("RTGraphics streams not supported"); + break; + + default: + error("Unknown StreamComponent type: %d", s->choice); + break; + } + return; } Modified: redbutton-browser/trunk/TODO =================================================================== --- redbutton-browser/trunk/TODO 2006-05-12 12:46:29 UTC (rev 55) +++ redbutton-browser/trunk/TODO 2006-05-14 09:56:06 UTC (rev 56) @@ -1,3 +1,10 @@ +check if default audio/video PID is 0 in rb-download +if it is, avstream fails + + +print avstream error message in rb-browser if openStream fails + + use -t timeout when searching for initial object to boot Modified: redbutton-browser/trunk/VideoClass.c =================================================================== --- redbutton-browser/trunk/VideoClass.c 2006-05-12 12:46:29 UTC (rev 55) +++ redbutton-browser/trunk/VideoClass.c 2006-05-14 09:56:06 UTC (rev 56) @@ -354,6 +354,14 @@ } void +VideoClass_setStreamPlayer(VideoClass *t, MHEGStreamPlayer *p) +{ + t->inst.player = p; + + return; +} + +void VideoClass_render(VideoClass *t, MHEGDisplay *d, XYPosition *pos, OriginalBoxSize *box) { XYPosition ins_pos; @@ -364,14 +372,13 @@ if(!intersects(pos, box, &t->inst.Position, &t->inst.BoxSize, &ins_pos, &ins_box)) return; -/* TODO */ -//printf("TODO: VideoClass_render; component_tag=%d\n", t->component_tag); -/* so we can see where it is for now */ -{ -MHEGColour col = { 0, 255, 0, 0 }; -MHEGDisplay_fillRectangle(d, &ins_pos, &ins_box, &col); -} + /* draw the video frame onto the Window contents Pixmap */ + if(t->inst.player != NULL) + MHEGStreamPlayer_drawCurrentFrame(t->inst.player); + /* make a transparent hole in the MHEG overlay so we can see the video below it */ + MHEGDisplay_fillTransparentRectangle(d, &ins_pos, &ins_box); + return; } Modified: redbutton-browser/trunk/VideoClass.h =================================================================== --- redbutton-browser/trunk/VideoClass.h 2006-05-12 12:46:29 UTC (rev 55) +++ redbutton-browser/trunk/VideoClass.h 2006-05-14 09:56:06 UTC (rev 56) @@ -25,6 +25,7 @@ void VideoClass_GetVideoDecodeOffset(VideoClass *, GetVideoDecodeOffset *, OctetString *); void VideoClass_ScaleVideo(VideoClass *, ScaleVideo *, OctetString *); +void VideoClass_setStreamPlayer(VideoClass *, MHEGStreamPlayer *); void VideoClass_render(VideoClass *, MHEGDisplay *, XYPosition *, OriginalBoxSize *); #endif /* __VIDEOCLASS_H__ */ Modified: redbutton-browser/trunk/add_instance_vars.conf =================================================================== --- redbutton-browser/trunk/add_instance_vars.conf 2006-05-12 12:46:29 UTC (rev 55) +++ redbutton-browser/trunk/add_instance_vars.conf 2006-05-14 09:56:06 UTC (rev 56) @@ -175,6 +175,8 @@ /* VideoClass */ /* UK MHEG Profile adds this */ XYPosition VideoDecodeOffset; + /* we add this */ + struct MHEGStreamPlayer *player; } VideoClassInstanceVars; </VideoClass> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-05-12 12:46:35
|
Revision: 55 Author: skilvington Date: 2006-05-12 05:46:29 -0700 (Fri, 12 May 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=55&view=rev Log Message: ----------- more TODO items Modified Paths: -------------- redbutton-browser/trunk/TODO Modified: redbutton-browser/trunk/TODO =================================================================== --- redbutton-browser/trunk/TODO 2006-05-11 13:00:18 UTC (rev 54) +++ redbutton-browser/trunk/TODO 2006-05-12 12:46:29 UTC (rev 55) @@ -1,3 +1,6 @@ +use -t timeout when searching for initial object to boot + + handle SIGPIPE - default handler terminates the process This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-05-11 13:00:26
|
Revision: 54 Author: skilvington Date: 2006-05-11 06:00:18 -0700 (Thu, 11 May 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=54&view=rev Log Message: ----------- add video decoder (output disabled until we can overlay the other MHEG objects) Modified Paths: -------------- redbutton-browser/trunk/MHEGDisplay.c redbutton-browser/trunk/MHEGStreamPlayer.c redbutton-browser/trunk/MHEGStreamPlayer.h redbutton-browser/trunk/Makefile redbutton-browser/trunk/StreamComponent.c Modified: redbutton-browser/trunk/MHEGDisplay.c =================================================================== --- redbutton-browser/trunk/MHEGDisplay.c 2006-05-11 11:40:42 UTC (rev 53) +++ redbutton-browser/trunk/MHEGDisplay.c 2006-05-11 13:00:18 UTC (rev 54) @@ -15,6 +15,7 @@ #include <X11/keysym.h> #include <mpeg2dec/mpeg2.h> #include <mpeg2dec/mpeg2convert.h> +#include <ffmpeg/avformat.h> #include "MHEGEngine.h" #include "MHEGDisplay.h" @@ -93,6 +94,9 @@ else d->keymap = default_keymap; + /* so X requests/replies in different threads don't get interleaved */ + XInitThreads(); + if((d->dpy = XOpenDisplay(NULL)) == NULL) fatal("Unable to open display"); @@ -236,6 +240,9 @@ d->app = XtCreateApplicationContext(); XtDisplayInitialize(d->app, d->dpy, APP_NAME, APP_CLASS, NULL, 0, &argc, argv); + /* init ffmpeg */ + av_register_all(); + return; } Modified: redbutton-browser/trunk/MHEGStreamPlayer.c =================================================================== --- redbutton-browser/trunk/MHEGStreamPlayer.c 2006-05-11 11:40:42 UTC (rev 53) +++ redbutton-browser/trunk/MHEGStreamPlayer.c 2006-05-11 13:00:18 UTC (rev 54) @@ -4,19 +4,76 @@ #include <string.h> #include <stdio.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <X11/Xlib.h> +#include <X11/extensions/XShm.h> #include "MHEGEngine.h" #include "MHEGStreamPlayer.h" +#include "mpegts.h" #include "utils.h" +/* internal routines */ +static void *decode_thread(void *); +static void *video_thread(void *); + +static void thread_usleep(unsigned long); +static enum PixelFormat find_av_pix_fmt(int, unsigned long, unsigned long, unsigned long); +static enum CodecID find_av_codec_id(int); + +LIST_TYPE(VideoFrame) * +new_VideoFrameListItem(double pts, enum PixelFormat pix_fmt, unsigned int width, unsigned int height, AVFrame *frame) +{ + LIST_TYPE(VideoFrame) *vf = safe_malloc(sizeof(LIST_TYPE(VideoFrame))); + int frame_size; + + vf->item.pts = pts; + vf->item.pix_fmt = pix_fmt; + vf->item.width = width; + vf->item.height = height; + + /* + * take a copy of the frame, + * the actual data is inside the video codec somewhere and will be overwritten by the next frame we decode + */ + if((frame_size = avpicture_get_size(pix_fmt, width, height)) < 0) + fatal("Invalid frame_size"); + vf->item.frame_data = safe_malloc(frame_size); + avpicture_fill(&vf->item.frame, vf->item.frame_data, pix_fmt, width, height); + img_copy(&vf->item.frame, (AVPicture*) frame, pix_fmt, width, height); + + return vf; +} + void +free_VideoFrameListItem(LIST_TYPE(VideoFrame) *vf) +{ + safe_free(vf->item.frame_data); + + safe_free(vf); + + return; +} + +void MHEGStreamPlayer_init(MHEGStreamPlayer *p) { bzero(p, sizeof(MHEGStreamPlayer)); + p->playing = false; + p->stop = false; + p->have_video = false; p->have_audio = false; + p->video = NULL; + + pthread_mutex_init(&p->videoq_lock, NULL); + p->videoq = NULL; + + pthread_mutex_init(&p->current_frame_lock, NULL); + return; } @@ -25,11 +82,14 @@ { MHEGStreamPlayer_stop(p); + pthread_mutex_destroy(&p->videoq_lock); + pthread_mutex_destroy(&p->current_frame_lock); + return; } void -MHEGStreamPlayer_setVideoTag(MHEGStreamPlayer *p, int tag) +MHEGStreamPlayer_setVideoTag(MHEGStreamPlayer *p, VideoClass *video, int tag) { if(p->have_video) error("MHEGStreamPlayer: more than one video stream; only using the last one (%d)", tag); @@ -37,7 +97,11 @@ p->have_video = true; p->video_tag = tag; p->video_pid = -1; + p->video_type = -1; + /* output size/position */ + p->video = video; + return; } @@ -50,6 +114,7 @@ p->have_audio = true; p->audio_tag = tag; p->audio_pid = -1; + p->audio_type = -1; return; } @@ -61,11 +126,27 @@ p->audio_pid = p->audio_tag; p->video_pid = p->video_tag; -// if((p->ts = MHEGEngine_openStream(p->have_audio, &p->audio_pid, p->have_video, &p->video_pid)) == NULL) -// error("Unable to open MPEG stream"); -/* TODO */ -printf("TODO: MHEGStreamPlayer_play: not yet implemented\n"); + if((p->ts = MHEGEngine_openStream(p->have_audio, &p->audio_pid, &p->audio_type, + p->have_video, &p->video_pid, &p->video_type)) == NULL) + { + error("Unable to open MPEG stream"); + return; + } + p->playing = true; + p->stop = false; + + /* + * we have two threads: + * decode_thread reads MPEG data from the TS and decodes it into YUV video frames + * video_thread takes YUV frames off the videoq list, converts them to RGB and displays them on the screen + */ + if(pthread_create(&p->decode_tid, NULL, decode_thread, p) != 0) + fatal("Unable to create MPEG decoder thread"); + + if(pthread_create(&p->video_tid, NULL, video_thread, p) != 0) + fatal("Unable to create video output thread"); + return; } @@ -74,12 +155,473 @@ { verbose("MHEGStreamPlayer_stop"); + /* are we playing */ + if(!p->playing) + return; + + /* signal the threads to stop */ + p->stop = true; + + /* wait for them to finish */ + pthread_join(p->decode_tid, NULL); + pthread_join(p->video_tid, NULL); + + /* clean up */ + LIST_FREE(&p->videoq, VideoFrame, free_VideoFrameListItem); + if(p->ts != NULL) { fclose(p->ts); p->ts = NULL; } + p->playing = false; + return; } +/* + * decode_thread + * reads the MPEG TS file + * decodes the data into YUV video frames + * adds them to the tail of the videoq list + */ + +static void * +decode_thread(void *arg) +{ + MHEGStreamPlayer *p = (MHEGStreamPlayer *) arg; + MpegTSContext *tsdemux; + AVPacket pkt; + AVCodecContext *audio_codec_ctx = NULL; + AVCodecContext *video_codec_ctx = NULL; + enum CodecID codec_id; + AVCodec *codec = NULL; + double video_time_base = 90000.0; + double pts; + AVFrame *frame; + LIST_TYPE(VideoFrame) *video_frame; + int got_picture; + + verbose("MHEGStreamPlayer: decode thread started"); + + if(p->video_pid != -1) + { + if((video_codec_ctx = avcodec_alloc_context()) == NULL) + fatal("Out of memory"); + if((codec_id = find_av_codec_id(p->video_type)) == CODEC_ID_NONE + || (codec = avcodec_find_decoder(codec_id)) == NULL) + fatal("Unsupported video codec"); + if(avcodec_open(video_codec_ctx, codec) < 0) + fatal("Unable to open video codec"); + verbose("MHEGStreamPlayer: Video: stream type=%d codec=%s\n", p->video_type, codec->name); + } + + if(p->audio_pid != -1) + { + if((audio_codec_ctx = avcodec_alloc_context()) == NULL) + fatal("Out of memory"); + if((codec_id = find_av_codec_id(p->audio_type)) == CODEC_ID_NONE + || (codec = avcodec_find_decoder(codec_id)) == NULL) + fatal("Unsupported audio codec"); + if(avcodec_open(audio_codec_ctx, codec) < 0) + fatal("Unable to open audio codec"); + verbose("MHEGStreamPlayer: Audio: stream type=%d codec=%s\n", p->audio_type, codec->name); + } + + if((frame = avcodec_alloc_frame()) == NULL) + fatal("Out of memory"); + + if((tsdemux = mpegts_open(p->ts)) == NULL) + fatal("Out of memory"); + + while(!p->stop && !feof(p->ts)) + { + /* get the next complete packet for one of the streams */ + if(mpegts_demux_frame(tsdemux, &pkt) < 0) + continue; +//if(pkt.dts == AV_NOPTS_VALUE) printf("NO DTS on PID %d!\n", pkt.stream_index); +//if(pkt.pts == AV_NOPTS_VALUE) printf("NO PTS on PID %d!\n", pkt.stream_index); +//printf("PTS=%lld DTS=%lld\n", pkt.pts, pkt.dts); + /* see what stream we got a packet for */ + if(pkt.stream_index == p->audio_pid && pkt.dts != AV_NOPTS_VALUE) + { +//printf("decode: got audio packet\n"); + } + else if(pkt.stream_index == p->video_pid && pkt.dts != AV_NOPTS_VALUE) + { +//printf("decode: got video packet\n"); + (void) avcodec_decode_video(video_codec_ctx, frame, &got_picture, pkt.data, pkt.size); + if(got_picture) + { + pts = pkt.dts / video_time_base; + video_frame = new_VideoFrameListItem(pts, video_codec_ctx->pix_fmt, video_codec_ctx->width, video_codec_ctx->height, frame); + pthread_mutex_lock(&p->videoq_lock); + LIST_APPEND(&p->videoq, video_frame); + pthread_mutex_unlock(&p->videoq_lock); +//printf("decode: got video frame: pts=%f (real pts=%f) width=%d height=%d\n", pts, pkt.pts / video_time_base, video_codec_ctx->width, video_codec_ctx->height); + } + } + else + { +//printf("decode: got unknown/untimed packet\n"); + } + av_free_packet(&pkt); + } + + /* clean up */ + mpegts_close(tsdemux); + + av_free(frame); + + if(video_codec_ctx != NULL) + avcodec_close(video_codec_ctx); + if(audio_codec_ctx != NULL) + avcodec_close(audio_codec_ctx); + + verbose("MHEGStreamPlayer: decode thread stopped"); + + return NULL; +} + +/* + * video_thread + * takes YUV frames off the videoq list + * scales them (if necessary) to fit the output size + * converts them to RGB + * waits for the correct time, then displays them on the screen + */ + +static void * +video_thread(void *arg) +{ + MHEGStreamPlayer *p = (MHEGStreamPlayer *) arg; + MHEGDisplay *d = MHEGEngine_getDisplay(); + unsigned int out_width = 0; /* keep the compiler happy */ + unsigned int out_height = 0; + VideoFrame *vf; + AVPicture rgb_frame; + int rgb_size; + XShmSegmentInfo shm; + enum PixelFormat out_format; + double buffered; + double last_pts; + int64_t last_time, this_time, now; + int usecs; + bool drop_frame; + ImgReSampleContext *resize_ctx = NULL; + AVPicture resized_frame; + AVPicture *yuv_frame; + int tmpbuf_size; + uint8_t *tmpbuf_data = NULL; + unsigned int nframes = 0; + + verbose("MHEGStreamPlayer: video thread started"); + + /* assert */ + if(p->video == NULL) + fatal("video_thread: VideoClass is NULL"); + + /* wait until we have some frames buffered up */ + do + { + pthread_mutex_lock(&p->videoq_lock); + if(p->videoq != NULL) + buffered = p->videoq->prev->item.pts - p->videoq->item.pts; + else + buffered = 0.0; + pthread_mutex_unlock(&p->videoq_lock); + verbose("MHEGStreamPlayer: buffered %f seconds", buffered); + /* let the decoder have a go */ + if(buffered < INIT_VIDEO_BUFFER_WAIT) + pthread_yield(); + } + while(!p->stop && buffered < INIT_VIDEO_BUFFER_WAIT); + + /* do we need to bomb out early */ + if(p->stop) + return NULL; + + /* assert */ + if(p->videoq == NULL) + fatal("video_thread: no frames!"); + + /* size of first frame, no need to lock as item won't change */ + out_width = p->videoq->item.width; + out_height = p->videoq->item.height; +/* TODO */ +/* also scale if ScaleVideo has been called */ + if(d->fullscreen) + { + out_width = (out_width * d->xres) / MHEG_XRES; + out_height = (out_height * d->yres) / MHEG_YRES; + } + + if((p->current_frame = XShmCreateImage(d->dpy, d->vis, d->depth, ZPixmap, NULL, &shm, out_width, out_height)) == NULL) + fatal("XShmCreateImage failed"); + + /* work out what ffmpeg pixel format matches our XImage format */ + if((out_format = find_av_pix_fmt(p->current_frame->bits_per_pixel, + d->vis->red_mask, d->vis->green_mask, d->vis->blue_mask)) == PIX_FMT_NONE) + fatal("Unsupported XImage pixel format"); + + rgb_size = p->current_frame->bytes_per_line * out_height; + + if(rgb_size != avpicture_get_size(out_format, out_width, out_height)) + fatal("XImage and ffmpeg pixel formats differ"); + + if((shm.shmid = shmget(IPC_PRIVATE, rgb_size, IPC_CREAT | 0777)) == -1) + fatal("shmget failed"); + if((shm.shmaddr = shmat(shm.shmid, NULL, 0)) == (void *) -1) + fatal("shmat failed"); + shm.readOnly = True; + if(!XShmAttach(d->dpy, &shm)) + fatal("XShmAttach failed"); + + /* we made sure these pixel formats are the same */ + p->current_frame->data = shm.shmaddr; + avpicture_fill(&rgb_frame, shm.shmaddr, out_format, out_width, out_height); + + /* the time that we displayed the previous frame */ + last_time = 0; + last_pts = 0; + + /* until we are told to stop... */ + while(!p->stop) + { + /* get the next frame */ + pthread_mutex_lock(&p->videoq_lock); + vf = (p->videoq != NULL) ? &p->videoq->item : NULL; + /* only we delete items from the videoq, so vf will stay valid */ + pthread_mutex_unlock(&p->videoq_lock); + if(vf == NULL) + { + verbose("MHEGStreamPlayer: videoq is empty"); + /* give the decoder a bit of time to catch up */ + pthread_yield(); + continue; + } + /* + * keep track of how many frames we've played + * just so the dropped frame verbose message below is more useful + * don't care if it wraps back to 0 again + */ + nframes ++; + /* see if we should drop this frame or not */ + now = av_gettime(); + /* work out when this frame should be displayed based on when the last one was */ + if(last_time != 0) + this_time = last_time + ((vf->pts - last_pts) * 1000000.0); + else + this_time = now; + /* how many usecs do we need to wait */ + usecs = this_time - now; + /* + * we've still got to convert it to RGB and maybe scale it too + * so don't bother allowing any error here + */ + drop_frame = (usecs < 0); + if(drop_frame) + verbose("MHEGStreamPlayer: dropped frame %u (usecs=%d)", nframes, usecs); +//if(drop_frame) +//printf("dropped frame %d: pts=%f last_pts=%f last_time=%lld this_time=%lld usecs=%d\n", nframes, vf->pts, last_pts, last_time, this_time, usecs); + if(!drop_frame) + { + /* see if the output size has changed */ +/* TODO */ + /* scale the next frame if necessary */ + if(vf->width != out_width || vf->height != out_height) + { +/* TODO */ +/* need to change resize_ctx if vf->width or vf->height have changed since last time */ +/* dont forget: img_resample_close(resize_ctx); */ +/* and to free or realloc tmpbuf_data */ + if(resize_ctx == NULL) + { + resize_ctx = img_resample_init(out_width, out_height, vf->width, vf->height); + tmpbuf_size = avpicture_get_size(vf->pix_fmt, out_width, out_height); + tmpbuf_data = safe_malloc(tmpbuf_size); + avpicture_fill(&resized_frame, tmpbuf_data, vf->pix_fmt, out_width, out_height); + } + img_resample(resize_ctx, &resized_frame, &vf->frame); + yuv_frame = &resized_frame; + } + else + { + yuv_frame = &vf->frame; + } + /* make sure no-one else is using the RGB frame */ + pthread_mutex_lock(&p->current_frame_lock); + /* convert the next frame to RGB */ + img_convert(&rgb_frame, out_format, yuv_frame, vf->pix_fmt, out_width, out_height); +/* TODO */ +/* overlay any MHEG objects above it */ + /* we've finished changing the RGB frame now */ + pthread_mutex_unlock(&p->current_frame_lock); + /* wait until it's time to display the frame */ + now = av_gettime(); + /* don't wait if this is the first frame */ + if(last_time != 0) + { + /* how many usecs do we need to wait */ + usecs = this_time - now; +//printf("last_time=%lld this_time=%lld now=%lld sleep=%d\n", last_time, this_time, now, usecs); + if(usecs > 0) + thread_usleep(usecs); + /* remember when we should have displayed this frame */ + last_time = this_time; + } + else + { + /* remember when we displayed this frame */ + last_time = now; + } + /* remember the time stamp for this frame */ + last_pts = vf->pts; +//now=av_gettime(); +//printf("display frame %d: pts=%f this_time=%lld real_time=%lld (diff=%lld)\n", ++nframes, vf->pts, last_time, now, now-last_time); +/* TODO */ +/* take p->video size/position into account */ +/* redraw objects above the video */ +// disable output until we can overlay the MHEG objects +// XShmPutImage(d->dpy, d->win, d->win_gc, p->current_frame, 0, 0, 0, 0, out_width, out_height, False); + /* get it drawn straight away */ + XFlush(d->dpy); + } + /* we can delete the frame from the queue now */ + pthread_mutex_lock(&p->videoq_lock); + LIST_FREE_HEAD(&p->videoq, VideoFrame, free_VideoFrameListItem); + pthread_mutex_unlock(&p->videoq_lock); + } + + if(resize_ctx != NULL) + { + img_resample_close(resize_ctx); + safe_free(tmpbuf_data); + } + + /* the XImage data is our shared memory, make sure XDestroyImage doesn't try to free it */ + p->current_frame->data = NULL; + XDestroyImage(p->current_frame); + + XShmDetach(d->dpy, &shm); + shmdt(shm.shmaddr); + shmctl(shm.shmid, IPC_RMID, NULL); + + verbose("MHEGStreamPlayer: video thread stopped"); + + return NULL; +} + +/* + * usleep(usecs) + * need to make sure the other threads get a go while we are sleeping + */ + +static void +thread_usleep(unsigned long usecs) +{ + struct timespec ts; + + ts.tv_sec = (usecs / 1000000); + ts.tv_nsec = (usecs % 1000000) * 1000; + + nanosleep(&ts, NULL); + + return; +} + +/* + * returns a PIX_FMT_xxx type that matches the given bits per pixel and RGB bit mask values + * returns PIX_FMT_NONE if none match + */ + +static enum PixelFormat +find_av_pix_fmt(int bpp, unsigned long rmask, unsigned long gmask, unsigned long bmask) +{ + enum PixelFormat fmt; + + fmt = PIX_FMT_NONE; + switch(bpp) + { + case 32: + if(rmask == 0xff0000 && gmask == 0xff00 && bmask == 0xff) + fmt = PIX_FMT_RGBA32; + break; + + case 24: + if(rmask == 0xff0000 && gmask == 0xff00 && bmask == 0xff) + fmt = PIX_FMT_RGB24; + else if(rmask == 0xff && gmask == 0xff00 && bmask == 0xff0000) + fmt = PIX_FMT_BGR24; + break; + + case 16: + if(rmask == 0xf800 && gmask == 0x07e0 && bmask == 0x001f) + fmt = PIX_FMT_RGB565; + else if(rmask == 0x7c00 && gmask == 0x03e0 && bmask == 0x001f) + fmt = PIX_FMT_RGB555; + break; + + default: + break; + } + + if(fmt == PIX_FMT_NONE) + error("Unsupported pixel format (bpp=%d r=%lx g=%lx b=%lx)", bpp, rmask, gmask, bmask); + + return fmt; +} + +/* + * from libavformat/mpegts.c + */ + +static enum CodecID +find_av_codec_id(int stream_type) +{ + enum CodecID codec_id; + + codec_id = CODEC_ID_NONE; + switch(stream_type) + { + case STREAM_TYPE_AUDIO_MPEG1: + case STREAM_TYPE_AUDIO_MPEG2: + codec_id = CODEC_ID_MP3; + break; + + case STREAM_TYPE_VIDEO_MPEG1: + case STREAM_TYPE_VIDEO_MPEG2: + codec_id = CODEC_ID_MPEG2VIDEO; + break; + + case STREAM_TYPE_VIDEO_MPEG4: + codec_id = CODEC_ID_MPEG4; + break; + + case STREAM_TYPE_VIDEO_H264: + codec_id = CODEC_ID_H264; + break; + + case STREAM_TYPE_AUDIO_AAC: + codec_id = CODEC_ID_AAC; + break; + + case STREAM_TYPE_AUDIO_AC3: + codec_id = CODEC_ID_AC3; + break; + + case STREAM_TYPE_AUDIO_DTS: + codec_id = CODEC_ID_DTS; + break; + + default: + break; + } + + if(codec_id == CODEC_ID_NONE) + error("Unsupported audio/video codec (MPEG stream type=%d)", stream_type); + + return codec_id; +} + Modified: redbutton-browser/trunk/MHEGStreamPlayer.h =================================================================== --- redbutton-browser/trunk/MHEGStreamPlayer.h 2006-05-11 11:40:42 UTC (rev 53) +++ redbutton-browser/trunk/MHEGStreamPlayer.h 2006-05-11 13:00:18 UTC (rev 54) @@ -6,22 +6,59 @@ #define __MHEGSTREAMPLAYER_H__ #include <stdbool.h> +#include <pthread.h> +#include <X11/Xlib.h> +#include <ffmpeg/avformat.h> +#include <ffmpeg/avcodec.h> +#include "ISO13522-MHEG-5.h" + +/* seconds of video to buffer before we start playing it */ +#define INIT_VIDEO_BUFFER_WAIT 1.0 + +/* list of decoded video frames to be displayed */ typedef struct { - bool have_video; /* false if we have no video stream */ - bool have_audio; /* false if we have no audio stream */ - int video_tag; /* video stream component tag (-1 => default for current service ID) */ - int audio_tag; /* audio stream component tag (-1 => default for current service ID) */ - int video_pid; /* PID in MPEG Transport Stream (-1 => not yet known) */ - int audio_pid; /* PID in MPEG Transport Stream (-1 => not yet known) */ - FILE *ts; /* MPEG Transport Stream */ + double pts; /* presentation time stamp */ + enum PixelFormat pix_fmt; + unsigned int width; + unsigned int height; + AVPicture frame; + unsigned char *frame_data; +} VideoFrame; + +DEFINE_LIST_OF(VideoFrame); + +LIST_TYPE(VideoFrame) *new_VideoFrameListItem(double, enum PixelFormat, unsigned int, unsigned int, AVFrame *); +void free_VideoFrameListItem(LIST_TYPE(VideoFrame) *); + +/* player state */ +typedef struct +{ + bool playing; /* true when our threads are active */ + bool stop; /* true => stop playback */ + bool have_video; /* false if we have no video stream */ + bool have_audio; /* false if we have no audio stream */ + int video_tag; /* video stream component tag (-1 => default for current service ID) */ + int video_pid; /* PID in MPEG Transport Stream (-1 => not yet known) */ + int video_type; /* video stream type (-1 => not yet known) */ + int audio_tag; /* audio stream component tag (-1 => default for current service ID) */ + int audio_pid; /* PID in MPEG Transport Stream (-1 => not yet known) */ + int audio_type; /* audio stream type (-1 => not yet known) */ + FILE *ts; /* MPEG Transport Stream */ + VideoClass *video; /* output size/position, maybe NULL if audio only */ + pthread_t decode_tid; /* thread decoding the MPEG stream into frames */ + pthread_t video_tid; /* thread displaying frames on the screen */ + pthread_mutex_t videoq_lock; /* list of decoded video frames */ + LIST_OF(VideoFrame) *videoq; /* head of list is next to be displayed */ + pthread_mutex_t current_frame_lock; /* locked when we are updating current frame */ + XImage *current_frame; /* frame we are currently displaying */ } MHEGStreamPlayer; void MHEGStreamPlayer_init(MHEGStreamPlayer *); void MHEGStreamPlayer_fini(MHEGStreamPlayer *); -void MHEGStreamPlayer_setVideoTag(MHEGStreamPlayer *, int); +void MHEGStreamPlayer_setVideoTag(MHEGStreamPlayer *, VideoClass *, int); void MHEGStreamPlayer_setAudioTag(MHEGStreamPlayer *, int); void MHEGStreamPlayer_play(MHEGStreamPlayer *); Modified: redbutton-browser/trunk/Makefile =================================================================== --- redbutton-browser/trunk/Makefile 2006-05-11 11:40:42 UTC (rev 53) +++ redbutton-browser/trunk/Makefile 2006-05-11 13:00:18 UTC (rev 54) @@ -1,9 +1,10 @@ CC=gcc CFLAGS=-Wall -O2 -#DEFS=-DDEBUG_ALLOC +DEFS=-D_REENTRANT -D_GNU_SOURCE +#DEFS=-DDEBUG_ALLOC -D_REENTRANT -D_GNU_SOURCE INCS=`freetype-config --cflags` -LIBS=-lm -lz -L/usr/X11R6/lib -lX11 -lXt -lXrender -lXft -lpng -lmpeg2 -lmpeg2convert -lavformat -lavcodec +LIBS=-lm -lz -L/usr/X11R6/lib -lX11 -lXt -lXrender -lXft -lpng -lmpeg2 -lmpeg2convert -lavformat -lavcodec -lpthread CLASSES=ActionClass.o \ ApplicationClass.o \ Modified: redbutton-browser/trunk/StreamComponent.c =================================================================== --- redbutton-browser/trunk/StreamComponent.c 2006-05-11 11:40:42 UTC (rev 53) +++ redbutton-browser/trunk/StreamComponent.c 2006-05-11 13:00:18 UTC (rev 54) @@ -109,7 +109,7 @@ break; case StreamComponent_video: - MHEGStreamPlayer_setVideoTag(player, s->u.video.component_tag); + MHEGStreamPlayer_setVideoTag(player, &s->u.video, s->u.video.component_tag); break; case StreamComponent_rtgraphics: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-05-11 11:40:47
|
Revision: 53 Author: skilvington Date: 2006-05-11 04:40:42 -0700 (Thu, 11 May 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=53&view=rev Log Message: ----------- add MPEG stream type constants Modified Paths: -------------- redbutton-browser/trunk/mpegts.h Modified: redbutton-browser/trunk/mpegts.h =================================================================== --- redbutton-browser/trunk/mpegts.h 2006-05-11 11:02:42 UTC (rev 52) +++ redbutton-browser/trunk/mpegts.h 2006-05-11 11:40:42 UTC (rev 53) @@ -5,6 +5,17 @@ #ifndef __MPEGTS_H__ #define __MPEGTS_H__ +/* stream types we care about */ +#define STREAM_TYPE_VIDEO_MPEG1 0x01 +#define STREAM_TYPE_VIDEO_MPEG2 0x02 +#define STREAM_TYPE_AUDIO_MPEG1 0x03 +#define STREAM_TYPE_AUDIO_MPEG2 0x04 +#define STREAM_TYPE_AUDIO_AAC 0x0f +#define STREAM_TYPE_VIDEO_MPEG4 0x10 +#define STREAM_TYPE_VIDEO_H264 0x1b +#define STREAM_TYPE_AUDIO_AC3 0x81 +#define STREAM_TYPE_AUDIO_DTS 0x8a + typedef struct MpegTSContext MpegTSContext; MpegTSContext *mpegts_open(FILE *); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-05-11 11:02:56
|
Revision: 52 Author: skilvington Date: 2006-05-11 04:02:42 -0700 (Thu, 11 May 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=52&view=rev Log Message: ----------- return MPEG stream types to client Modified Paths: -------------- redbutton-browser/trunk/MHEGBackend.c redbutton-browser/trunk/MHEGBackend.h redbutton-browser/trunk/MHEGEngine.c redbutton-browser/trunk/MHEGEngine.h redbutton-download/trunk/assoc.c redbutton-download/trunk/assoc.h redbutton-download/trunk/command.c redbutton-download/trunk/findmheg.c redbutton-download/trunk/module.h Modified: redbutton-browser/trunk/MHEGBackend.c =================================================================== --- redbutton-browser/trunk/MHEGBackend.c 2006-05-11 08:54:07 UTC (rev 51) +++ redbutton-browser/trunk/MHEGBackend.c 2006-05-11 11:02:42 UTC (rev 52) @@ -17,7 +17,7 @@ bool local_checkContentRef(MHEGBackend *, ContentReference *); bool local_loadFile(MHEGBackend *, OctetString *, OctetString *); FILE *local_openFile(MHEGBackend *, OctetString *); -FILE *local_openStream(MHEGBackend *, bool, int *, bool, int *); +FILE *local_openStream(MHEGBackend *, bool, int *, int *, bool, int *, int *); static struct MHEGBackendFns local_backend_fns = { @@ -31,7 +31,7 @@ bool remote_checkContentRef(MHEGBackend *, ContentReference *); bool remote_loadFile(MHEGBackend *, OctetString *, OctetString *); FILE *remote_openFile(MHEGBackend *, OctetString *); -FILE *remote_openStream(MHEGBackend *, bool, int *, bool, int *); +FILE *remote_openStream(MHEGBackend *, bool, int *, int *, bool, int *, int *); static struct MHEGBackendFns remote_backend_fns = { @@ -327,11 +327,12 @@ * the *audio_tag and *video_tag numbers refer to Component/Association Tag values from the DVB PMT * if *audio_tag or *video_tag is -1, the default audio and/or video stream for the current Service ID is used * updates *audio_tag and/or *video_tag to the actual PIDs in the Transport Stream + * updates *audio_type and/or *video_type to the stream type IDs * returns NULL on error */ FILE * -local_openStream(MHEGBackend *t, bool have_audio, int *audio_tag, bool have_video, int *video_tag) +local_openStream(MHEGBackend *t, bool have_audio, int *audio_tag, int *audio_type, bool have_video, int *video_tag, int *video_type) { /* * we need to convert the audio/video_tag into PIDs @@ -341,7 +342,7 @@ * 3. just stream the TS from the backend * we choose 3, to avoid duplicating code and having to pass "-d <device>" options etc */ - return remote_openStream(t, have_audio, audio_tag, have_video, video_tag); + return remote_openStream(t, have_audio, audio_tag, audio_type, have_video, video_tag, video_type); } /* @@ -475,11 +476,12 @@ * the *audio_tag and *video_tag numbers refer to Component/Association Tag values from the DVB PMT * if *audio_tag or *video_tag is -1, the default audio and/or video stream for the current Service ID is used * updates *audio_tag and/or *video_tag to the actual PIDs in the Transport Stream + * updates *audio_type and/or *video_type to the stream type IDs * returns NULL on error */ FILE * -remote_openStream(MHEGBackend *t, bool have_audio, int *audio_tag, bool have_video, int *video_tag) +remote_openStream(MHEGBackend *t, bool have_audio, int *audio_tag, int *audio_type, bool have_video, int *video_tag, int *video_type) { char cmd[PATH_MAX]; FILE *sock; @@ -515,11 +517,12 @@ /* update the PID variables */ if(have_audio && have_video) - err = (sscanf(pids, "AudioPID %u VideoPID %u", &audio_pid, &video_pid) != 2); + err = (sscanf(pids, "AudioPID %u AudioType %u VideoPID %u VideoType %u", + &audio_pid, audio_type, &video_pid, video_type) != 4); else if(have_audio) - err = (sscanf(pids, "AudioPID %u", &audio_pid) != 1); + err = (sscanf(pids, "AudioPID %u AudioType %u", &audio_pid, audio_type) != 2); else - err = (sscanf(pids, "VideoPID %u", &video_pid) != 1); + err = (sscanf(pids, "VideoPID %u VideoType %u", &video_pid, video_type) != 2); if(!err) { Modified: redbutton-browser/trunk/MHEGBackend.h =================================================================== --- redbutton-browser/trunk/MHEGBackend.h 2006-05-11 08:54:07 UTC (rev 51) +++ redbutton-browser/trunk/MHEGBackend.h 2006-05-11 11:02:42 UTC (rev 52) @@ -20,10 +20,14 @@ /* function pointers */ struct MHEGBackendFns { - bool (*checkContentRef)(struct MHEGBackend *, ContentReference *); /* check a carousel file exists */ - bool (*loadFile)(struct MHEGBackend *, OctetString *, OctetString *); /* load a carousel file */ - FILE *(*openFile)(struct MHEGBackend *, OctetString *); /* open a carousel file */ - FILE *(*openStream)(struct MHEGBackend *, bool, int *, bool, int *); /* open an MPEG Transport Stream */ + /* check a carousel file exists */ + bool (*checkContentRef)(struct MHEGBackend *, ContentReference *); + /* load a carousel file */ + bool (*loadFile)(struct MHEGBackend *, OctetString *, OctetString *); + /* open a carousel file */ + FILE *(*openFile)(struct MHEGBackend *, OctetString *); + /* open an MPEG Transport Stream */ + FILE *(*openStream)(struct MHEGBackend *, bool, int *, int *, bool, int *, int *); } *fns; } MHEGBackend; Modified: redbutton-browser/trunk/MHEGEngine.c =================================================================== --- redbutton-browser/trunk/MHEGEngine.c 2006-05-11 08:54:07 UTC (rev 51) +++ redbutton-browser/trunk/MHEGEngine.c 2006-05-11 11:02:42 UTC (rev 52) @@ -1340,9 +1340,11 @@ */ FILE * -MHEGEngine_openStream(bool have_audio, int *audio_tag, bool have_video, int *video_tag) +MHEGEngine_openStream(bool have_audio, int *audio_tag, int *audio_type, bool have_video, int *video_tag, int *video_type) { - return (*(engine.backend.fns->openStream))(&engine.backend, have_audio, audio_tag, have_video, video_tag); + return (*(engine.backend.fns->openStream))(&engine.backend, + have_audio, audio_tag, audio_type, + have_video, video_tag, video_type); } /* Modified: redbutton-browser/trunk/MHEGEngine.h =================================================================== --- redbutton-browser/trunk/MHEGEngine.h 2006-05-11 08:54:07 UTC (rev 51) +++ redbutton-browser/trunk/MHEGEngine.h 2006-05-11 11:02:42 UTC (rev 52) @@ -221,7 +221,7 @@ bool MHEGEngine_checkContentRef(ContentReference *); bool MHEGEngine_loadFile(OctetString *, OctetString *); FILE *MHEGEngine_openFile(OctetString *); -FILE *MHEGEngine_openStream(bool, int *, bool, int *); +FILE *MHEGEngine_openStream(bool, int *, int *, bool, int *, int *); char *MHEGEngine_absoluteFilename(OctetString *); Modified: redbutton-download/trunk/assoc.c =================================================================== --- redbutton-download/trunk/assoc.c 2006-05-11 08:54:07 UTC (rev 51) +++ redbutton-download/trunk/assoc.c 2006-05-11 11:02:42 UTC (rev 52) @@ -35,20 +35,23 @@ a->nassocs = 0; a->pids = NULL; a->sids = NULL; + a->types = NULL; return; } void -add_assoc(struct assoc *a, uint16_t elementary_pid, uint16_t stream_id) +add_assoc(struct assoc *a, uint16_t elementary_pid, uint16_t stream_id, uint8_t stream_type) { a->nassocs ++; a->pids = safe_realloc(a->pids, a->nassocs * sizeof(uint16_t)); a->sids = safe_realloc(a->sids, a->nassocs * sizeof(uint16_t)); + a->types = safe_realloc(a->types, a->nassocs * sizeof(uint8_t)); a->pids[a->nassocs - 1] = elementary_pid; a->sids[a->nassocs - 1] = stream_id; + a->types[a->nassocs - 1] = stream_type; return; } @@ -69,4 +72,19 @@ return 0; } +uint8_t +stream2type(struct assoc *a, uint16_t stream_id) +{ + unsigned int i; + for(i=0; i<a->nassocs; i++) + { + if(a->sids[i] == stream_id) + return a->types[i]; + } + + error("Unknown stream type for association tag 0x%x", stream_id); + + return 0; +} + Modified: redbutton-download/trunk/assoc.h =================================================================== --- redbutton-download/trunk/assoc.h 2006-05-11 08:54:07 UTC (rev 51) +++ redbutton-download/trunk/assoc.h 2006-05-11 11:02:42 UTC (rev 52) @@ -32,12 +32,14 @@ unsigned int nassocs; uint16_t *pids; uint16_t *sids; + uint8_t *types; /* stream type */ }; void init_assoc(struct assoc *); -void add_assoc(struct assoc *, uint16_t, uint16_t); +void add_assoc(struct assoc *, uint16_t, uint16_t, uint8_t); uint16_t stream2pid(struct assoc *, uint16_t); +uint8_t stream2type(struct assoc *, uint16_t); #endif /* __ASSOC_H__ */ Modified: redbutton-download/trunk/command.c =================================================================== --- redbutton-download/trunk/command.c 2006-05-11 08:54:07 UTC (rev 51) +++ redbutton-download/trunk/command.c 2006-05-11 11:02:42 UTC (rev 52) @@ -140,6 +140,7 @@ struct carousel *car = listen_data->carousel; int tag; uint16_t pid; + uint8_t type; int audio_fd; int ts_fd; char hdr[64]; @@ -148,11 +149,17 @@ tag = strtol(argv[1], NULL, 0); - /* map the tag to a PID, or use the default */ + /* map the tag to a PID and stream type, or use the default */ if(tag == -1) + { pid = car->audio_pid; + type = car->audio_type; + } else + { pid = stream2pid(&car->assoc, tag); + type = stream2type(&car->assoc, tag); + } /* add the PID to the demux device */ if((audio_fd = add_demux_filter(car->demux_device, pid, DMX_PES_AUDIO)) < 0) @@ -172,8 +179,8 @@ /* send the OK code */ SEND_RESPONSE(200, "OK"); - /* tell the client what PID the component tag resolved to */ - snprintf(hdr, sizeof(hdr), "AudioPID %u\n", pid); + /* tell the client what PID and stream type the component tag resolved to */ + snprintf(hdr, sizeof(hdr), "AudioPID %u AudioType %u\n", pid, type); fputs(hdr, client); /* shovel the transport stream to client until the client closes or we get an error */ @@ -201,6 +208,7 @@ struct carousel *car = listen_data->carousel; int tag; uint16_t pid; + uint8_t type; int video_fd; int ts_fd; char hdr[64]; @@ -209,11 +217,17 @@ tag = strtol(argv[1], NULL, 0); - /* map the tag to a PID, or use the default */ + /* map the tag to a PID and stream type, or use the default */ if(tag == -1) + { pid = car->video_pid; + type = car->video_type; + } else + { pid = stream2pid(&car->assoc, tag); + type = stream2type(&car->assoc, tag); + } /* add the PID to the demux device */ if((video_fd = add_demux_filter(car->demux_device, pid, DMX_PES_VIDEO)) < 0) @@ -233,8 +247,8 @@ /* send the OK code */ SEND_RESPONSE(200, "OK"); - /* tell the client what PID the component tag resolved to */ - snprintf(hdr, sizeof(hdr), "VideoPID %u\n", pid); + /* tell the client what PID and stream type the component tag resolved to */ + snprintf(hdr, sizeof(hdr), "VideoPID %u VideoType %u\n", pid, type); fputs(hdr, client); /* shovel the transport stream down client_sock until the client closes it or we get an error */ @@ -264,6 +278,8 @@ int video_tag; uint16_t audio_pid; uint16_t video_pid; + uint8_t audio_type; + uint8_t video_type; int audio_fd; int video_fd; int ts_fd; @@ -274,16 +290,28 @@ audio_tag = strtol(argv[1], NULL, 0); video_tag = strtol(argv[2], NULL, 0); - /* map the tags to PIDs, or use the defaults */ + /* map the tags to PIDs and stream types, or use the defaults */ if(audio_tag == -1) + { audio_pid = car->audio_pid; + audio_type = car->audio_type; + } else + { audio_pid = stream2pid(&car->assoc, audio_tag); + audio_type = stream2type(&car->assoc, audio_tag); + } if(video_tag == -1) + { video_pid = car->video_pid; + video_type = car->video_type; + } else + { video_pid = stream2pid(&car->assoc, video_tag); + video_type = stream2type(&car->assoc, video_tag); + } /* add the PIDs to the demux device */ if((audio_fd = add_demux_filter(car->demux_device, audio_pid, DMX_PES_AUDIO)) < 0) @@ -310,8 +338,8 @@ /* send the OK code */ SEND_RESPONSE(200, "OK"); - /* tell the client what PIDs the component tags resolved to */ - snprintf(hdr, sizeof(hdr), "AudioPID %u VideoPID %u\n", audio_pid, video_pid); + /* tell the client what PIDs and stream types the component tags resolved to */ + snprintf(hdr, sizeof(hdr), "AudioPID %u AudioType %u VideoPID %uVideoType %u\n", audio_pid, audio_type, video_pid, video_type); fputs(hdr, client); /* shovel the transport stream down client_sock until the client closes it or we get an error */ Modified: redbutton-download/trunk/findmheg.c =================================================================== --- redbutton-download/trunk/findmheg.c 2006-05-11 08:54:07 UTC (rev 51) +++ redbutton-download/trunk/findmheg.c 2006-05-11 11:02:42 UTC (rev 52) @@ -111,7 +111,9 @@ /* unknown */ _car.carousel_id = 0; _car.audio_pid = 0; + _car.audio_type = 0; _car.video_pid = 0; + _car.video_type = 0; _car.current_pid = 0; /* map between stream_id_descriptors and elementary_PIDs */ init_assoc(&_car.assoc); @@ -173,7 +175,10 @@ offset += 2; /* is it the default video stream for this service */ if(stream_type == STREAM_TYPE_VIDEO_MPEG2) + { _car.video_pid = elementary_pid; + _car.video_type = stream_type; + } /* read the descriptors */ info_length = ((pmt[offset] & 0x0f) << 8) + pmt[offset+1]; offset += 2; @@ -200,7 +205,7 @@ desc = (struct stream_id_descriptor *) &pmt[offset]; component_tag = desc->component_tag; // printf("pid=0x%x component_tag=0x%x\n", elementary_pid, component_tag); - add_assoc(&_car.assoc, elementary_pid, desc->component_tag); + add_assoc(&_car.assoc, elementary_pid, desc->component_tag, stream_type); } else if(desc_tag == TAG_LANGUAGE_DESCRIPTOR && is_audio_stream(stream_type)) { @@ -208,7 +213,10 @@ desc = (struct language_descriptor *) &pmt[offset]; /* only remember the normal audio stream (not visually impaired stream) */ if(desc->audio_type == 0) + { _car.audio_pid = elementary_pid; + _car.audio_type = stream_type; + } } offset += desc_length; info_length -= desc_length; Modified: redbutton-download/trunk/module.h =================================================================== --- redbutton-download/trunk/module.h 2006-05-11 08:54:07 UTC (rev 51) +++ redbutton-download/trunk/module.h 2006-05-11 11:02:42 UTC (rev 52) @@ -61,7 +61,9 @@ uint16_t service_id; uint32_t carousel_id; uint16_t audio_pid; /* PID of default audio stream for this service_id */ + uint8_t audio_type; /* type ID of default audio stream */ uint16_t video_pid; /* PID of default video stream for this service_id */ + uint8_t video_type; /* type ID of default video stream */ uint16_t current_pid; /* PID we downloaded the last table from */ struct assoc assoc; /* map stream_id's to elementary_pid's */ int32_t npids; /* PIDs we are reading data from */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-05-11 08:54:11
|
Revision: 51 Author: skilvington Date: 2006-05-11 01:54:07 -0700 (Thu, 11 May 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=51&view=rev Log Message: ----------- remove debug code Modified Paths: -------------- redbutton-download/trunk/stream.c Modified: redbutton-download/trunk/stream.c =================================================================== --- redbutton-download/trunk/stream.c 2006-05-11 08:28:54 UTC (rev 50) +++ redbutton-download/trunk/stream.c 2006-05-11 08:54:07 UTC (rev 51) @@ -43,7 +43,6 @@ if(ioctl(fd, DMX_SET_PES_FILTER, &pes_filter) < 0) { error("ioctl DMX_SET_PES_FILTER: %s", strerror(errno)); -error("pid=%d type=%d", pid, pes_type); close(fd); return -1; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-05-11 08:28:57
|
Revision: 50 Author: skilvington Date: 2006-05-11 01:28:54 -0700 (Thu, 11 May 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=50&view=rev Log Message: ----------- spacing Modified Paths: -------------- redbutton-download/trunk/stream.c Modified: redbutton-download/trunk/stream.c =================================================================== --- redbutton-download/trunk/stream.c 2006-05-11 08:27:18 UTC (rev 49) +++ redbutton-download/trunk/stream.c 2006-05-11 08:28:54 UTC (rev 50) @@ -37,7 +37,7 @@ * on my Nova-T card, there is no hardware MPEG decoder so setting the pes_type to DMX_PES_VIDEO returns an error (sometimes!) * anyway, always setting it to DMX_PES_OTHER works for me */ - pes_type=DMX_PES_OTHER; + pes_type = DMX_PES_OTHER; pes_filter.pes_type = pes_type; if(ioctl(fd, DMX_SET_PES_FILTER, &pes_filter) < 0) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-05-11 08:27:30
|
Revision: 49 Author: skilvington Date: 2006-05-11 01:27:18 -0700 (Thu, 11 May 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=49&view=rev Log Message: ----------- always set PES filter type to DMX_PES_OTHER Modified Paths: -------------- redbutton-download/trunk/stream.c Modified: redbutton-download/trunk/stream.c =================================================================== --- redbutton-download/trunk/stream.c 2006-05-10 13:36:14 UTC (rev 48) +++ redbutton-download/trunk/stream.c 2006-05-11 08:27:18 UTC (rev 49) @@ -28,11 +28,22 @@ pes_filter.output = DMX_OUT_TS_TAP; pes_filter.flags = DMX_IMMEDIATE_START; pes_filter.pid = pid; + /* + * I think the way pes_type works is like this: + * if you set it to DMX_PES_VIDEO then the output goes to the dvr0 device (as a TS) + * but it also ends up on the video0 device (presumably as decoded video frames) + * similarly for DMX_PES_AUDIO + * if we set the pes_type to DMX_PES_OTHER then the output only goes to the dvr0 device + * on my Nova-T card, there is no hardware MPEG decoder so setting the pes_type to DMX_PES_VIDEO returns an error (sometimes!) + * anyway, always setting it to DMX_PES_OTHER works for me + */ + pes_type=DMX_PES_OTHER; pes_filter.pes_type = pes_type; if(ioctl(fd, DMX_SET_PES_FILTER, &pes_filter) < 0) { error("ioctl DMX_SET_PES_FILTER: %s", strerror(errno)); +error("pid=%d type=%d", pid, pes_type); close(fd); return -1; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-05-10 13:36:23
|
Revision: 48 Author: skilvington Date: 2006-05-10 06:36:14 -0700 (Wed, 10 May 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=48&view=rev Log Message: ----------- allow more audio stream types Modified Paths: -------------- redbutton-download/trunk/findmheg.c Modified: redbutton-download/trunk/findmheg.c =================================================================== --- redbutton-download/trunk/findmheg.c 2006-05-10 11:07:12 UTC (rev 47) +++ redbutton-download/trunk/findmheg.c 2006-05-10 13:36:14 UTC (rev 48) @@ -38,8 +38,9 @@ #define TID_PMT 0x02 /* stream_types we are interested in */ -#define STREAM_TYPE_VIDEO 0x02 -#define STREAM_TYPE_AUDIO 0x03 +#define STREAM_TYPE_VIDEO_MPEG2 0x02 +#define STREAM_TYPE_AUDIO_MPEG1 0x03 +#define STREAM_TYPE_AUDIO_MPEG2 0x04 #define STREAM_TYPE_ISO13818_6_B 0x0b /* descriptors we want */ @@ -64,6 +65,20 @@ uint8_t audio_type; } __attribute__((__packed__)); +bool +is_audio_stream(uint8_t stream_type) +{ + switch(stream_type) + { + case STREAM_TYPE_AUDIO_MPEG1: + case STREAM_TYPE_AUDIO_MPEG2: + return true; + + default: + return false; + } +} + /* * fills in a struct carousel based on the given service_id * returns a ptr to a static struct that will be overwritten be the next call to this routine @@ -157,7 +172,7 @@ elementary_pid = ((pmt[offset] & 0x1f) << 8) + pmt[offset+1]; offset += 2; /* is it the default video stream for this service */ - if(stream_type == STREAM_TYPE_VIDEO) + if(stream_type == STREAM_TYPE_VIDEO_MPEG2) _car.video_pid = elementary_pid; /* read the descriptors */ info_length = ((pmt[offset] & 0x0f) << 8) + pmt[offset+1]; @@ -187,7 +202,7 @@ // printf("pid=0x%x component_tag=0x%x\n", elementary_pid, component_tag); add_assoc(&_car.assoc, elementary_pid, desc->component_tag); } - else if(desc_tag == TAG_LANGUAGE_DESCRIPTOR && stream_type == STREAM_TYPE_AUDIO) + else if(desc_tag == TAG_LANGUAGE_DESCRIPTOR && is_audio_stream(stream_type)) { struct language_descriptor *desc; desc = (struct language_descriptor *) &pmt[offset]; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-05-10 11:07:19
|
Revision: 47 Author: skilvington Date: 2006-05-10 04:07:12 -0700 (Wed, 10 May 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=47&view=rev Log Message: ----------- avoid NULL ptr dereference Modified Paths: -------------- redbutton-browser/trunk/mpegts.c Modified: redbutton-browser/trunk/mpegts.c =================================================================== --- redbutton-browser/trunk/mpegts.c 2006-05-08 15:55:52 UTC (rev 46) +++ redbutton-browser/trunk/mpegts.c 2006-05-10 11:07:12 UTC (rev 47) @@ -210,8 +210,11 @@ for(i=0; i<NB_PID_MAX; i++) { - av_free(ctx->pids[i]->frame_data); - av_free(ctx->pids[i]); + if(ctx->pids[i]) + { + av_free(ctx->pids[i]->frame_data); + av_free(ctx->pids[i]); + } } av_free(ctx); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-05-08 15:55:58
|
Revision: 46 Author: skilvington Date: 2006-05-08 08:55:52 -0700 (Mon, 08 May 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=46&view=rev Log Message: ----------- don't block when input closes Modified Paths: -------------- redbutton-browser/trunk/mpegts.c Modified: redbutton-browser/trunk/mpegts.c =================================================================== --- redbutton-browser/trunk/mpegts.c 2006-05-06 19:31:53 UTC (rev 45) +++ redbutton-browser/trunk/mpegts.c 2006-05-08 15:55:52 UTC (rev 46) @@ -115,7 +115,11 @@ do { - mpegts_demux_packet(ctx, &packet); + if(mpegts_demux_packet(ctx, &packet) < 0) + { + av_free_packet(&packet); + return -1; + } /* find the stream */ if((pes = add_pes_stream(ctx, packet.stream_index)) == NULL) fatal("mpegts_demux_frame: internal error"); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-05-06 19:32:13
|
Revision: 45 Author: skilvington Date: 2006-05-06 12:31:53 -0700 (Sat, 06 May 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=45&view=rev Log Message: ----------- don't like ffmpeg coding style Modified Paths: -------------- redbutton-browser/trunk/mpegts.c Modified: redbutton-browser/trunk/mpegts.c =================================================================== --- redbutton-browser/trunk/mpegts.c 2006-05-06 08:27:03 UTC (rev 44) +++ redbutton-browser/trunk/mpegts.c 2006-05-06 19:31:53 UTC (rev 45) @@ -188,14 +188,13 @@ ctx->pkt = pkt; ctx->stop_parse = 0; - for(;;) + do { - if(ctx->stop_parse) - break; if((ret = read_packet(ctx->ts_stream, packet)) != 0) return ret; handle_packet(ctx, packet); } + while(ctx->stop_parse == 0); return 0; } @@ -365,7 +364,7 @@ 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 unbounded */ - if (pes->total_size) + if(pes->total_size) pes->total_size += 6; pes->pes_header_size = pes->header[8] + 9; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-05-06 08:27:11
|
Revision: 44 Author: skilvington Date: 2006-05-06 01:27:03 -0700 (Sat, 06 May 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=44&view=rev Log Message: ----------- only realloc when needed Modified Paths: -------------- redbutton-browser/trunk/mpegts.c Modified: redbutton-browser/trunk/mpegts.c =================================================================== --- redbutton-browser/trunk/mpegts.c 2006-05-02 15:41:28 UTC (rev 43) +++ redbutton-browser/trunk/mpegts.c 2006-05-06 08:27:03 UTC (rev 44) @@ -37,6 +37,8 @@ #define TS_PACKET_SIZE 188 #define NB_PID_MAX 2 +/* expands as necessary */ +#define INIT_FRAME_BUFF_SIZE (128 * 1024) typedef struct PESContext PESContext; @@ -77,7 +79,8 @@ int64_t frame_pts; int64_t frame_dts; uint8_t *frame_data; - unsigned int frame_size; + unsigned int frame_size; /* number of bytes of valid data in frame_data */ + unsigned int alloc_size; /* number of bytes malloc'ed to frame_data */ }; static int read_packet(FILE *, uint8_t *); @@ -108,6 +111,7 @@ { AVPacket packet; PESContext *pes; + uint8_t *frame_data; do { @@ -119,7 +123,12 @@ if(ctx->is_start == 0) { /* not a new frame, add data to the exisiting one */ - pes->frame_data = safe_realloc(pes->frame_data, pes->frame_size + packet.size); + if((frame_data = av_fast_realloc(pes->frame_data, &pes->alloc_size, pes->frame_size + packet.size)) == NULL) + { + av_free_packet(&packet); + return -1; + } + pes->frame_data = frame_data; memcpy(pes->frame_data + pes->frame_size, packet.data, packet.size); pes->frame_size += packet.size; av_free_packet(&packet); @@ -145,7 +154,13 @@ frame->dts = pes->frame_dts; /* copy the first packet of the next frame into PES context */ - pes->frame_data = safe_realloc(pes->frame_data, packet.size); + if((frame_data = av_fast_realloc(pes->frame_data, &pes->alloc_size, packet.size)) == NULL) + { + av_free_packet(&packet); + av_free_packet(frame); + return -1; + } + pes->frame_data = frame_data; pes->frame_size = packet.size; memcpy(pes->frame_data, packet.data, packet.size); @@ -192,7 +207,7 @@ for(i=0; i<NB_PID_MAX; i++) { - safe_free(ctx->pids[i]->frame_data); + av_free(ctx->pids[i]->frame_data); av_free(ctx->pids[i]); } av_free(ctx); @@ -293,6 +308,13 @@ pes->ts = ctx; pes->pid = pid; + pes->alloc_size = INIT_FRAME_BUFF_SIZE; + if((pes->frame_data = av_malloc(pes->alloc_size)) == NULL) + { + av_free(pes); + return NULL; + } + pes->frame_pts = AV_NOPTS_VALUE; pes->frame_dts = AV_NOPTS_VALUE; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-05-02 15:41:35
|
Revision: 43 Author: skilvington Date: 2006-05-02 08:41:28 -0700 (Tue, 02 May 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=43&view=rev Log Message: ----------- free packet on error Modified Paths: -------------- redbutton-browser/trunk/mpegts.c Modified: redbutton-browser/trunk/mpegts.c =================================================================== --- redbutton-browser/trunk/mpegts.c 2006-05-02 15:02:06 UTC (rev 42) +++ redbutton-browser/trunk/mpegts.c 2006-05-02 15:41:28 UTC (rev 43) @@ -134,7 +134,10 @@ * copy it into the PES context for the stream */ if(av_new_packet(frame, pes->frame_size) != 0) + { + av_free_packet(&packet); return -1; + } memcpy(frame->data, pes->frame_data, pes->frame_size); frame->stream_index = pes->pid; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-05-02 15:02:17
|
Revision: 42 Author: skilvington Date: 2006-05-02 08:02:06 -0700 (Tue, 02 May 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=42&view=rev Log Message: ----------- return the correct PTS Modified Paths: -------------- redbutton-browser/trunk/mpegts.c Modified: redbutton-browser/trunk/mpegts.c =================================================================== --- redbutton-browser/trunk/mpegts.c 2006-05-02 13:02:15 UTC (rev 41) +++ redbutton-browser/trunk/mpegts.c 2006-05-02 15:02:06 UTC (rev 42) @@ -116,20 +116,8 @@ if((pes = add_pes_stream(ctx, packet.stream_index)) == NULL) fatal("mpegts_demux_frame: internal error"); /* is it the first packet of the next frame */ - if(ctx->is_start != 0) + if(ctx->is_start == 0) { - /* a new frame, remember its PTS (or calc from the previous one) */ - if(packet.pts == AV_NOPTS_VALUE && pes->frame_pts != AV_NOPTS_VALUE) - pes->frame_pts += 3600; - else - pes->frame_pts = packet.pts; - if(packet.dts == AV_NOPTS_VALUE && pes->frame_dts != AV_NOPTS_VALUE) - pes->frame_dts += 3600; - else - pes->frame_dts = packet.dts; - } - else - { /* not a new frame, add data to the exisiting one */ pes->frame_data = safe_realloc(pes->frame_data, pes->frame_size + packet.size); memcpy(pes->frame_data + pes->frame_size, packet.data, packet.size); @@ -141,7 +129,9 @@ /* * pes->frame_data contains the last frame + * copy it into the output packet * packet contains the first packet of the next frame + * copy it into the PES context for the stream */ if(av_new_packet(frame, pes->frame_size) != 0) return -1; @@ -156,6 +146,16 @@ pes->frame_size = packet.size; memcpy(pes->frame_data, packet.data, packet.size); + /* remember the new frame's PTS (or calc from the previous one) */ + if(packet.pts == AV_NOPTS_VALUE && pes->frame_pts != AV_NOPTS_VALUE) + pes->frame_pts += 3600; + else + pes->frame_pts = packet.pts; + if(packet.dts == AV_NOPTS_VALUE && pes->frame_dts != AV_NOPTS_VALUE) + pes->frame_dts += 3600; + else + pes->frame_dts = packet.dts; + av_free_packet(&packet); return 0; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-05-02 13:02:24
|
Revision: 41 Author: skilvington Date: 2006-05-02 06:02:15 -0700 (Tue, 02 May 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=41&view=rev Log Message: ----------- remove \n Modified Paths: -------------- redbutton-browser/trunk/mpegts.c Modified: redbutton-browser/trunk/mpegts.c =================================================================== --- redbutton-browser/trunk/mpegts.c 2006-05-02 13:00:11 UTC (rev 40) +++ redbutton-browser/trunk/mpegts.c 2006-05-02 13:02:15 UTC (rev 41) @@ -216,7 +216,7 @@ nread += fread(buf + nread, 1, TS_PACKET_SIZE - nread, ts); if(*buf != TS_SYNC_BYTE && !feof(ts)) { - error("MPEG TS demux: bad sync byte: 0x%02x\n", *buf); + error("MPEG TS demux: bad sync byte: 0x%02x", *buf); memmove(buf, buf + 1, TS_PACKET_SIZE - 1); nread = TS_PACKET_SIZE - 1; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-05-02 13:00:31
|
Revision: 40 Author: skilvington Date: 2006-05-02 06:00:11 -0700 (Tue, 02 May 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=40&view=rev Log Message: ----------- change printf() to error() Modified Paths: -------------- redbutton-browser/trunk/mpegts.c Modified: redbutton-browser/trunk/mpegts.c =================================================================== --- redbutton-browser/trunk/mpegts.c 2006-05-02 12:53:37 UTC (rev 39) +++ redbutton-browser/trunk/mpegts.c 2006-05-02 13:00:11 UTC (rev 40) @@ -216,7 +216,7 @@ nread += fread(buf + nread, 1, TS_PACKET_SIZE - nread, ts); if(*buf != TS_SYNC_BYTE && !feof(ts)) { - printf("Bad sync byte: 0x%02x\n", *buf); + error("MPEG TS demux: bad sync byte: 0x%02x\n", *buf); memmove(buf, buf + 1, TS_PACKET_SIZE - 1); nread = TS_PACKET_SIZE - 1; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-05-02 12:53:46
|
Revision: 39 Author: skilvington Date: 2006-05-02 05:53:37 -0700 (Tue, 02 May 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=39&view=rev Log Message: ----------- import MPEG transport stream demuxer Modified Paths: -------------- redbutton-browser/trunk/Makefile Added Paths: ----------- redbutton-browser/trunk/mpegts.c redbutton-browser/trunk/mpegts.h Modified: redbutton-browser/trunk/Makefile =================================================================== --- redbutton-browser/trunk/Makefile 2006-05-02 11:29:45 UTC (rev 38) +++ redbutton-browser/trunk/Makefile 2006-05-02 12:53:37 UTC (rev 39) @@ -3,7 +3,7 @@ #DEFS=-DDEBUG_ALLOC INCS=`freetype-config --cflags` -LIBS=-lm -lz -L/usr/X11R6/lib -lX11 -lXt -lXrender -lXft -lpng -lmpeg2 -lmpeg2convert +LIBS=-lm -lz -L/usr/X11R6/lib -lX11 -lXt -lXrender -lXft -lpng -lmpeg2 -lmpeg2convert -lavformat -lavcodec CLASSES=ActionClass.o \ ApplicationClass.o \ @@ -71,6 +71,7 @@ clone.o \ si.o \ readpng.o \ + mpegts.o \ utils.o default: rb-browser rb-keymap Added: redbutton-browser/trunk/mpegts.c =================================================================== --- redbutton-browser/trunk/mpegts.c (rev 0) +++ redbutton-browser/trunk/mpegts.c 2006-05-02 12:53:37 UTC (rev 39) @@ -0,0 +1,445 @@ +/* + * mpegts.c + */ + +/* + * MPEG2 Transport Stream demuxer + * based on ffmpeg/libavformat code + * changed to avoid any seeking on the input + */ + +/* + * MPEG2 transport stream (aka DVB) demux + * Copyright (c) 2002-2003 Fabrice Bellard. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <ffmpeg/avformat.h> + +#include "mpegts.h" +#include "utils.h" + +#define TS_PACKET_SIZE 188 +#define NB_PID_MAX 2 + +typedef struct PESContext PESContext; + +struct MpegTSContext +{ + FILE *ts_stream; /* transport stream we are reading from */ + AVPacket *pkt; /* packet containing av data */ + int stop_parse; /* stop parsing loop */ + PESContext *pids[NB_PID_MAX]; /* PIDs we are demuxing */ + int is_start; /* is the current packet the first of a frame */ +}; + +/* TS stream handling */ +enum MpegTSState +{ + MPEGTS_SKIP = 0, /* must be 0, => don't start getting data until we have set is_start flag */ + MPEGTS_HEADER, + MPEGTS_PESHEADER_FILL, + MPEGTS_PAYLOAD, +}; + +/* enough for PES header + length */ +#define PES_START_SIZE 9 +#define MAX_PES_HEADER_SIZE (9 + 255) + +struct PESContext +{ + int pid; + MpegTSContext *ts; + enum MpegTSState state; + /* used to get the format */ + int data_index; + int total_size; + int pes_header_size; + int64_t pts, dts; + uint8_t header[MAX_PES_HEADER_SIZE]; + /* frame we are currently building for this stream */ + int64_t frame_pts; + int64_t frame_dts; + uint8_t *frame_data; + unsigned int frame_size; +}; + +static int read_packet(FILE *, uint8_t *); +static void handle_packet(MpegTSContext *, const uint8_t *); +static PESContext *add_pes_stream(MpegTSContext *, int); +static void mpegts_push_data(PESContext *, const uint8_t *, int, int); +static int64_t get_pts(const uint8_t *); + +/* my interface */ + +MpegTSContext * +mpegts_open(FILE *ts) +{ + MpegTSContext *ctx; + + if((ctx = av_mallocz(sizeof(MpegTSContext))) == NULL) + return NULL; + + ctx->ts_stream = ts; + + ctx->is_start = 0; + + return ctx; +} + +int +mpegts_demux_frame(MpegTSContext *ctx, AVPacket *frame) +{ + AVPacket packet; + PESContext *pes; + + do + { + mpegts_demux_packet(ctx, &packet); + /* find the stream */ + if((pes = add_pes_stream(ctx, packet.stream_index)) == NULL) + fatal("mpegts_demux_frame: internal error"); + /* is it the first packet of the next frame */ + if(ctx->is_start != 0) + { + /* a new frame, remember its PTS (or calc from the previous one) */ + if(packet.pts == AV_NOPTS_VALUE && pes->frame_pts != AV_NOPTS_VALUE) + pes->frame_pts += 3600; + else + pes->frame_pts = packet.pts; + if(packet.dts == AV_NOPTS_VALUE && pes->frame_dts != AV_NOPTS_VALUE) + pes->frame_dts += 3600; + else + pes->frame_dts = packet.dts; + } + else + { + /* not a new frame, add data to the exisiting one */ + pes->frame_data = safe_realloc(pes->frame_data, pes->frame_size + packet.size); + memcpy(pes->frame_data + pes->frame_size, packet.data, packet.size); + pes->frame_size += packet.size; + av_free_packet(&packet); + } + } + while(ctx->is_start == 0); + + /* + * pes->frame_data contains the last frame + * packet contains the first packet of the next frame + */ + if(av_new_packet(frame, pes->frame_size) != 0) + return -1; + memcpy(frame->data, pes->frame_data, pes->frame_size); + + frame->stream_index = pes->pid; + frame->pts = pes->frame_pts; + frame->dts = pes->frame_dts; + + /* copy the first packet of the next frame into PES context */ + pes->frame_data = safe_realloc(pes->frame_data, packet.size); + pes->frame_size = packet.size; + memcpy(pes->frame_data, packet.data, packet.size); + + av_free_packet(&packet); + + return 0; +} + +int +mpegts_demux_packet(MpegTSContext *ctx, AVPacket *pkt) +{ + uint8_t packet[TS_PACKET_SIZE]; + int ret; + + ctx->pkt = pkt; + + ctx->stop_parse = 0; + for(;;) + { + if(ctx->stop_parse) + break; + if((ret = read_packet(ctx->ts_stream, packet)) != 0) + return ret; + handle_packet(ctx, packet); + } + + return 0; +} + +void +mpegts_close(MpegTSContext *ctx) +{ + int i; + + for(i=0; i<NB_PID_MAX; i++) + { + safe_free(ctx->pids[i]->frame_data); + av_free(ctx->pids[i]); + } + av_free(ctx); + + return; +} + +/* internal functions */ + +/* return -1 if error or EOF. Return 0 if OK. */ +#define TS_SYNC_BYTE 0x47 + +static int +read_packet(FILE *ts, uint8_t *buf) +{ + size_t nread; + + /* find the next sync byte */ + nread = 0; + do + { + /* read the whole of the next packet */ + while(nread != TS_PACKET_SIZE && !feof(ts)) + nread += fread(buf + nread, 1, TS_PACKET_SIZE - nread, ts); + if(*buf != TS_SYNC_BYTE && !feof(ts)) + { + printf("Bad sync byte: 0x%02x\n", *buf); + memmove(buf, buf + 1, TS_PACKET_SIZE - 1); + nread = TS_PACKET_SIZE - 1; + } + } + while(*buf != TS_SYNC_BYTE && !feof(ts)); + + if(feof(ts)) + return -1; + + return 0; +} + +/* handle one TS packet */ +static void +handle_packet(MpegTSContext *ctx, const uint8_t *packet) +{ + PESContext *pes; + int pid, afc; + const uint8_t *p, *p_end; + + pid = ((packet[1] & 0x1f) << 8) | packet[2]; + + if((pes = add_pes_stream(ctx, pid)) == NULL) + return; + + ctx->is_start = packet[1] & 0x40; + +#if 0 + /* continuity check (currently not used) */ + cc = (packet[3] & 0xf); + cc_ok = (tss->last_cc < 0) || ((((tss->last_cc + 1) & 0x0f) == cc)); + tss->last_cc = cc; +#endif + + /* skip adaptation field */ + afc = (packet[3] >> 4) & 3; + p = packet + 4; + if(afc == 0) /* reserved value */ + return; + if(afc == 2) /* adaptation field only */ + return; + if(afc == 3) /* skip adapation field */ + p += p[0] + 1; + + /* if past the end of packet, ignore */ + p_end = packet + TS_PACKET_SIZE; + if(p >= p_end) + return; + + mpegts_push_data(pes, p, p_end - p, ctx->is_start); + + return; +} + +static PESContext * +add_pes_stream(MpegTSContext *ctx, int pid) +{ + PESContext *pes; + int i; + + /* have we already added this PID */ + for(i=0; i<NB_PID_MAX && ctx->pids[i]!=NULL; i++) + if(ctx->pids[i]->pid == pid) + return ctx->pids[i]; + if(i == NB_PID_MAX) + return NULL; + + /* if no pid found, then add a pid context */ + if((pes = av_mallocz(sizeof(PESContext))) == NULL) + return NULL; + pes->ts = ctx; + pes->pid = pid; + + pes->frame_pts = AV_NOPTS_VALUE; + pes->frame_dts = AV_NOPTS_VALUE; + + ctx->pids[i] = pes; + + return pes; +} + +/* return non zero if a packet could be constructed */ +static void +mpegts_push_data(PESContext *pes, const uint8_t *buf, int buf_size, int is_start) +{ + MpegTSContext *ts = pes->ts; + const uint8_t *p; + int len, code; + + if(is_start) + { + pes->state = MPEGTS_HEADER; + pes->data_index = 0; + } + p = buf; + while(buf_size > 0) + { + switch(pes->state) + { + case MPEGTS_HEADER: + len = PES_START_SIZE - pes->data_index; + if(len > buf_size) + len = buf_size; + memcpy(pes->header + pes->data_index, p, len); + pes->data_index += len; + p += len; + buf_size -= len; + if(pes->data_index == PES_START_SIZE) + { + /* we got all the PES or section header. We can now decide */ + if(pes->header[0] == 0x00 + && pes->header[1] == 0x00 + && pes->header[2] == 0x01) + { + /* it must be an mpeg2 PES stream */ + code = pes->header[3] | 0x100; + if(!((code >= 0x1c0 && code <= 0x1df) + || (code >= 0x1e0 && code <= 0x1ef) + || (code == 0x1bd))) + 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 unbounded */ + if (pes->total_size) + pes->total_size += 6; + pes->pes_header_size = pes->header[8] + 9; + } + else + { + /* otherwise, it should be a table */ + /* skip packet */ + skip: + pes->state = MPEGTS_SKIP; + continue; + } + } + break; + + case MPEGTS_PESHEADER_FILL: + /* PES packing parsing */ + len = pes->pes_header_size - pes->data_index; + if(len > buf_size) + len = buf_size; + memcpy(pes->header + pes->data_index, p, len); + pes->data_index += len; + p += len; + buf_size -= len; + if(pes->data_index == pes->pes_header_size) + { + const uint8_t *r; + unsigned int flags; + flags = pes->header[7]; + r = pes->header + 9; + pes->pts = AV_NOPTS_VALUE; + pes->dts = AV_NOPTS_VALUE; + if((flags & 0xc0) == 0x80) + { + pes->pts = get_pts(r); + r += 5; + } + else if((flags & 0xc0) == 0xc0) + { + pes->pts = get_pts(r); + r += 5; + pes->dts = get_pts(r); + r += 5; + } + /* we got the full header. We parse it and get the payload */ + pes->state = MPEGTS_PAYLOAD; + } + break; + + case MPEGTS_PAYLOAD: + if(pes->total_size) + { + len = pes->total_size - pes->data_index; + if(len > buf_size) + len = buf_size; + } + else + { + len = buf_size; + } + if(len > 0) + { + AVPacket *pkt = ts->pkt; + if(av_new_packet(pkt, len) == 0) + { + memcpy(pkt->data, p, len); + pkt->stream_index = pes->pid; + pkt->pts = pes->pts; + pkt->dts = pes->dts; + /* reset pts values */ + pes->pts = AV_NOPTS_VALUE; + pes->dts = AV_NOPTS_VALUE; + ts->stop_parse = 1; + return; + } + } + buf_size = 0; + break; + + case MPEGTS_SKIP: + buf_size = 0; + break; + } + } + + return; +} + +static int64_t +get_pts(const uint8_t *p) +{ + int64_t pts; + int val; + + pts = (int64_t)((p[0] >> 1) & 0x07) << 30; + val = (p[1] << 8) | p[2]; + pts |= (int64_t)(val >> 1) << 15; + val = (p[3] << 8) | p[4]; + pts |= (int64_t)(val >> 1); + + return pts; +} + Added: redbutton-browser/trunk/mpegts.h =================================================================== --- redbutton-browser/trunk/mpegts.h (rev 0) +++ redbutton-browser/trunk/mpegts.h 2006-05-02 12:53:37 UTC (rev 39) @@ -0,0 +1,15 @@ +/* + * mpegts.h + */ + +#ifndef __MPEGTS_H__ +#define __MPEGTS_H__ + +typedef struct MpegTSContext MpegTSContext; + +MpegTSContext *mpegts_open(FILE *); +int mpegts_demux_frame(MpegTSContext *, AVPacket *); +int mpegts_demux_packet(MpegTSContext *, AVPacket *); +void mpegts_close(MpegTSContext *); + +#endif /* __MPEGTS_H__ */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-05-02 11:29:54
|
Revision: 38 Author: skilvington Date: 2006-05-02 04:29:45 -0700 (Tue, 02 May 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=38&view=rev Log Message: ----------- add safe_mallocz Modified Paths: -------------- redbutton-browser/trunk/utils.c redbutton-browser/trunk/utils.h Modified: redbutton-browser/trunk/utils.c =================================================================== --- redbutton-browser/trunk/utils.c 2006-04-03 11:02:48 UTC (rev 37) +++ redbutton-browser/trunk/utils.c 2006-05-02 11:29:45 UTC (rev 38) @@ -113,6 +113,16 @@ return buf; } +void * +safe_mallocz(size_t nbytes) +{ + void *buf = safe_malloc(nbytes); + + bzero(buf, nbytes); + + return buf; +} + /* * safe_realloc(NULL, n) == safe_malloc(n) * safe_realloc(x, 0) == safe_free(x) and returns NULL Modified: redbutton-browser/trunk/utils.h =================================================================== --- redbutton-browser/trunk/utils.h 2006-04-03 11:02:48 UTC (rev 37) +++ redbutton-browser/trunk/utils.h 2006-05-02 11:29:45 UTC (rev 38) @@ -38,6 +38,7 @@ int next_utf8(unsigned char *, int, int *); void *safe_malloc(size_t); +void *safe_mallocz(size_t); void *safe_realloc(void *, size_t); void safe_free(void *); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-04-03 11:03:00
|
Revision: 37 Author: skilvington Date: 2006-04-03 04:02:48 -0700 (Mon, 03 Apr 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=37&view=rev Log Message: ----------- fix tar make targets Modified Paths: -------------- redbutton-browser/trunk/Makefile redbutton-download/trunk/Makefile Modified: redbutton-browser/trunk/Makefile =================================================================== --- redbutton-browser/trunk/Makefile 2006-04-03 10:55:20 UTC (rev 36) +++ redbutton-browser/trunk/Makefile 2006-04-03 11:02:48 UTC (rev 37) @@ -110,9 +110,8 @@ rm -f rb-browser rb-keymap xsd2c dertest dertest-mheg.[ch] berdecode *.o ISO13522-MHEG-5.[ch] clone.[ch] rtti.h core TARDIR=`basename ${PWD}` -DATE=`date +%Y%m%d` tar: make clean - (cd ..; tar zcvf ${TARDIR}-${DATE}.tar.gz ${TARDIR}) + (cd ..; tar zcvf ${TARDIR}.tar.gz --exclude .svn ${TARDIR}) Modified: redbutton-download/trunk/Makefile =================================================================== --- redbutton-download/trunk/Makefile 2006-04-03 10:55:20 UTC (rev 36) +++ redbutton-download/trunk/Makefile 2006-04-03 11:02:48 UTC (rev 37) @@ -19,7 +19,6 @@ LIBS=-lz TARDIR=`basename ${PWD}` -DATE=`date +%Y%m%d` rb-download: ${OBJS} ${CC} ${CFLAGS} -o rb-download ${OBJS} ${LIBS} @@ -32,6 +31,5 @@ tar: make clean - (cd ..; tar zcvf ${TARDIR}-${DATE}.tar.gz ${TARDIR}) + (cd ..; tar zcvf ${TARDIR}.tar.gz --exclude .svn ${TARDIR}) - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-04-03 10:55:23
|
Revision: 36 Author: skilvington Date: 2006-04-03 03:55:20 -0700 (Mon, 03 Apr 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=36&view=rev Log Message: ----------- remove disttar make target Modified Paths: -------------- redbutton-browser/trunk/Makefile Modified: redbutton-browser/trunk/Makefile =================================================================== --- redbutton-browser/trunk/Makefile 2006-04-03 10:53:33 UTC (rev 35) +++ redbutton-browser/trunk/Makefile 2006-04-03 10:55:20 UTC (rev 36) @@ -116,7 +116,3 @@ make clean (cd ..; tar zcvf ${TARDIR}-${DATE}.tar.gz ${TARDIR}) -disttar: - make clean - (cd ..; tar zcvf ${TARDIR}-${DATE}.tar.gz --exclude docs ${TARDIR}) - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-04-03 10:53:42
|
Revision: 35 Author: skilvington Date: 2006-04-03 03:53:33 -0700 (Mon, 03 Apr 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=35&view=rev Log Message: ----------- add remote backend description to web page Modified Paths: -------------- www/index.html Modified: www/index.html =================================================================== --- www/index.html 2006-04-03 10:52:06 UTC (rev 34) +++ www/index.html 2006-04-03 10:53:33 UTC (rev 35) @@ -8,14 +8,17 @@ RedButton allows you to use the interactive MHEG applications broadcast with DVB digital TV services. MHEG replaces the text only services available with analogue TV. <P> -RedButton consists of two parts. The first, rb-download, allows MHEG data to be downloaded from a DVB service. The second, rb-browser, allows the downloaded MHEG applications to be displayed. +RedButton consists of two parts. The first, rb-download, allows MHEG data to be downloaded from a DVB service. +The second, rb-browser, allows the downloaded MHEG applications to be displayed. +Both rb-download and rb-browser can be run on the same host, +or rb-download can be run on a host with a DVB card and rb-browser can be run on a remote frontend without a DVB card. <P> The source for both is released under the GPL and can be <A HREF="http://sourceforge.net/project/showfiles.php?group_id=158629">downloaded here.</A> <P> Just un-tar them and type 'make'. <P> -You can browser the latest version of the source +You can browse the latest version of the source <A HREF="http://svn.sourceforge.net/redbutton/">here.</A> You can download the latest source code with the following Subversion command: <PRE> @@ -27,18 +30,31 @@ <H2>rb-download</H2> Usage: <PRE> -rb-download [-d <demux_device>] [-b <base_dir>] [-t <timeout>] [-c <carousel_id>] [<service_id>] +rb-download [-a <adapter>] [-b <base_dir>] [-t <timeout>] [-l[<listen_addr>]] [-c <carousel_id>] [<service_id>] </PRE> Download the DVB Object Carousel for the given channel onto the local hard disc. <P> -The default demux device is /dev/dvb/adapter0/demux0. -<P> If no directory is given with -b, files will be stored under the current directory. Note that <base_dir> must already exist and be writeable. <P> The default timeout is 10 seconds. If no DSM-CC data is found after this time, it is assumed none is being broadcast. <P> +The DVB devices used will be: +<ul> +<li>/dev/dvb/adapter0/demux0</li> +<li>/dev/dvb/adapter0/dvr0</li> +</ul> +use the -a option to change the adapter number (eg "-a 1" will use /dev/dvb/adapter1/demux0 etc). +<P> +If -l is given, rb-download listens on the network for commands from a remote rb-browser. +The default IP to listen on is 0.0.0.0 (ie all interfaces), the default TCP port is 10101. +The <listen_addr> should be given in the form "host:port", where host defaults to 0.0.0.0 and port defaults to 10101. +Eg, to listen on a different port, do "-l8080", +to only listen on the loop back, do "-l127.0.0.1" or on a different port too, do "-l127.0.0.1:8080". +NOTE: because -l may or may not take an argument, you must not put a space between the -l and the value +(otherwise, "rb-download -l 1234", is ambiguous - listen on port 1234 or use service_id 1234?). +<P> The <carousel_id> will normally be read from the PMT, but you can use the -c option to explicitly choose a carousel. <P> If no <service_id> is given, a list of possible channels (and their <service_id>) is printed. @@ -69,13 +85,29 @@ <H2>rb-browser</H2> Usage: <PRE> -rb-browser [-v] [-f] [-k <keymap_config_file>] [-t <timeout>] <service_gateway_dir> +rb-browser [-v] [-f] [-k <keymap_config_file>] [-t <timeout>] [-r] <service_gateway> </PRE> Display the MHEG apps downloaded with rb-download. -The <service_gateway_dir> should be one of the entries in the services directory, eg +<P> +The -r option means use a remote backend (rb-download running on another host). +If -r is specified, then <service_gateway> should be the host[:port] that "rb-download -l" is running on. +If -r is not specified, rb-download is running on the same machine +and <service_gateway> should be an entry in the services directory. +Eg, on a single host, do this: <PRE> +rb-download 4165 > /dev/null & rb-browser services/4165 </PRE> +To run the frontend on a different host, do this on the backend: +<PRE> +rb-download -l 4165 > /dev/null & +</PRE> +and run this on the frontend: +<PRE> +rb-browser -r 10.0.0.1 +</PRE> +where 10.0.0.1 is the IP or hostname of the backend. +<P> It will display the app in a window, use -f for full screen mode. <P> The -v flag enables verbose/debug mode. @@ -109,8 +141,7 @@ <P> To run it you need an X server that supports the Xrender extension and you need to have libpng, libmpeg2 and freetype2 installed. <H2>Notes</H2> -It's not finished yet! -It'll only draw text, rectangles and PNG bitmaps at the moment and some of the ElementaryActions are not yet implemented. +It'll only draw text, rectangles and bitmaps at the moment and some of the ElementaryActions are not yet implemented. However, it is enough to be usable. The main things missing are video and audio streams, at the moment it'll just draw a green box where any video should be. <P> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-04-03 10:52:21
|
Revision: 34 Author: skilvington Date: 2006-04-03 03:52:06 -0700 (Mon, 03 Apr 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=34&view=rev Log Message: ----------- Tagged rb-download 20060403 Added Paths: ----------- redbutton-download/tags/redbutton-download-20060403/ Copied: redbutton-download/tags/redbutton-download-20060403 (from rev 33, redbutton-download/trunk) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-04-03 10:51:22
|
Revision: 33 Author: skilvington Date: 2006-04-03 03:51:09 -0700 (Mon, 03 Apr 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=33&view=rev Log Message: ----------- Tagged rb-browser 20060403 Added Paths: ----------- redbutton-browser/tags/redbutton-browser-20060403/ Copied: redbutton-browser/tags/redbutton-browser-20060403 (from rev 32, redbutton-browser/trunk) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |