[MPlayer-dev-eng] [PATCH] better mythtv support
Reimar Döffinger
Reimar.Doeffinger at stud.uni-karlsruhe.de
Thu Jul 28 19:23:15 CEST 2005
Hi,
I modified the patch from gentoo portage so that it allows us to support
some more files without (hopefully) breaking anything that works
currently.
I left those parts of the original patch that would certainly break
something out, so it will not (yet?) support everything.
Please comment.
Greetings,
Reimar Döffinger
-------------- next part --------------
Index: etc/codecs.conf
===================================================================
RCS file: /cvsroot/mplayer/main/etc/codecs.conf,v
retrieving revision 1.424
diff -u -r1.424 codecs.conf
--- etc/codecs.conf 26 Jul 2005 10:11:56 -0000 1.424
+++ etc/codecs.conf 28 Jul 2005 17:13:25 -0000
@@ -98,6 +98,7 @@
info "NuppelVideo"
status working
fourcc NUV1 ; NUV1 is an internal MPlayer FOURCC
+ fourcc RJPG
driver nuv
out I420,IYUV
Index: libmpdemux/demux_nuv.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/demux_nuv.c,v
retrieving revision 1.13
diff -u -r1.13 demux_nuv.c
--- libmpdemux/demux_nuv.c 26 Jun 2005 15:15:38 -0000 1.13
+++ libmpdemux/demux_nuv.c 28 Jul 2005 17:14:05 -0000
@@ -43,6 +43,22 @@
nuv_position_t *current_position;
} nuv_priv_t;
+/**
+ * \brief find best matching bitrate (in kbps) out of a table
+ * \param bitrate bitrate to find best match for
+ * \return best match from table
+ */
+static int nearestBitrate(int bitrate) {
+ const int rates[17] = {8000, 16000, 24000, 32000, 40000, 48000, 56000,
+ 64000, 80000, 96000, 112000, 128000, 160000,
+ 192000, 224000, 256000, 320000};
+ int i;
+ for (i = 0; i < 16; i++) {
+ if ((rates[i] + rates[i + 1]) / 2 > bitrate)
+ break;
+ }
+ return rates[i];
+}
/**
* Seek to a position relative to the current position, indicated in time.
@@ -154,12 +170,19 @@
rtjpeg_frameheader.packetlength);
#endif
- /* Skip Seekpoint, Text and Sync for now */
+ /* Skip Seekpoint, Extended header and Sync for now */
if ((rtjpeg_frameheader.frametype == 'R') ||
- (rtjpeg_frameheader.frametype == 'T') ||
+ (rtjpeg_frameheader.frametype == 'X') ||
(rtjpeg_frameheader.frametype == 'S'))
return 1;
+ /* Skip seektable and text (these have a payload) */
+ if ((rtjpeg_frameheader.frametype == 'Q') ||
+ (rtjpeg_frameheader.frametype == 'T')) {
+ stream_skip(demuxer->stream, rtjpeg_frameheader.packetlength);
+ return 1;
+ }
+
if (((rtjpeg_frameheader.frametype == 'D') &&
(rtjpeg_frameheader.comptype == 'R')) ||
(rtjpeg_frameheader.frametype == 'V'))
@@ -183,7 +206,7 @@
} else
/* copy PCM only */
if (demuxer->audio && (rtjpeg_frameheader.frametype == 'A') &&
- (rtjpeg_frameheader.comptype == '0'))
+ 1 /*(rtjpeg_frameheader.comptype == '0')*/)
{
priv->current_audio_frame++;
if (want_audio) {
@@ -194,15 +217,99 @@
orig_pos + 12, 0 );
} else {
/* skip audio block */
- stream_seek ( demuxer->stream,
- stream_tell ( demuxer->stream )
- + rtjpeg_frameheader.packetlength );
+ stream_skip ( demuxer->stream,
+ rtjpeg_frameheader.packetlength );
}
}
return 1;
}
+/* Scan for the extended data in MythTV nuv streams */
+static int demux_xscan_nuv(demuxer_t* demuxer, int width, int height) {
+ int i;
+ int res = 0;
+ off_t orig_pos = stream_tell(demuxer->stream);
+ struct rtframeheader rtjpeg_frameheader;
+ struct extendeddata ext;
+ sh_video_t* sh_video = demuxer->video->sh;
+ sh_audio_t* sh_audio = demuxer->audio->sh;
+
+ for (i = 0; i < 2; ++i) {
+ if (stream_read(demuxer->stream, (char*)&rtjpeg_frameheader,
+ sizeof(rtjpeg_frameheader)) < sizeof(rtjpeg_frameheader))
+ goto out;
+
+ if (rtjpeg_frameheader.frametype != 'X')
+ stream_skip(demuxer->stream, rtjpeg_frameheader.packetlength);
+ }
+
+ if ( rtjpeg_frameheader.frametype != 'X' )
+ goto out;
+
+ if (rtjpeg_frameheader.packetlength != sizeof(ext)) {
+ mp_msg(MSGT_DEMUXER, MSGL_WARN,
+ "NUV extended frame does not have expected length, ignoring\n");
+ goto out;
+ }
+ le2me_extendeddata(&ext);
+
+ if (stream_read(demuxer->stream, (char*)&ext, sizeof(ext)) < sizeof(ext))
+ goto out;
+
+ if (ext.version != 1) {
+ mp_msg(MSGT_DEMUXER, MSGL_WARN,
+ "NUV extended frame has unknown version number (%d), ignoring\n",
+ ext.version);
+ goto out;
+ }
+
+ mp_msg(MSGT_DEMUXER, MSGL_V, "Detected MythTV stream\n");
+
+ /* Video parameters */
+ mp_msg(MSGT_DEMUXER, MSGL_V, "FOURCC: %c%c%c%c\n",
+ (ext.video_fourcc >> 24) & 0xff,
+ (ext.video_fourcc >> 16) & 0xff,
+ (ext.video_fourcc >> 8) & 0xff,
+ (ext.video_fourcc) & 0xff);
+ sh_video->format = ext.video_fourcc;
+ sh_video->i_bps = ext.lavc_bitrate;
+
+ /* Audio parameters */
+ if (ext.audio_fourcc == mmioFOURCC('L', 'A', 'M', 'E')) {
+ sh_audio->format = 0x55;
+ } else if (ext.audio_fourcc == mmioFOURCC('R', 'A', 'W', 'A')) {
+ sh_audio->format = 0x1;
+ } else {
+ mp_msg(MSGT_DEMUXER, MSGL_WARN,
+ "Unknown audio format 0x%x\n", ext.audio_fourcc);
+ }
+
+ sh_audio->channels = ext.audio_channels;
+ sh_audio->samplerate = ext.audio_sample_rate;
+ sh_audio->i_bps = sh_audio->channels * sh_audio->samplerate *
+ ext.audio_bits_per_sample;
+ if (sh_audio->format != 0x1)
+ sh_audio->i_bps = nearestBitrate(sh_audio->i_bps /
+ ext.audio_compression_ratio);
+ sh_audio->wf->wFormatTag = sh_audio->format;
+ sh_audio->wf->nChannels = sh_audio->channels;
+ sh_audio->wf->nSamplesPerSec = sh_audio->samplerate;
+ sh_audio->wf->nAvgBytesPerSec = sh_audio->i_bps / 8;
+ sh_audio->wf->nBlockAlign = sh_audio->channels * 2;
+ sh_audio->wf->wBitsPerSample = ext.audio_bits_per_sample;
+ sh_audio->wf->cbSize = 0;
+
+ mp_msg(MSGT_DEMUXER, MSGL_V,
+ "channels=%d bitspersample=%d samplerate=%d compression_ratio=%d\n",
+ ext.audio_channels, ext.audio_bits_per_sample,
+ ext.audio_sample_rate, ext.audio_compression_ratio);
+ return 1;
+out:
+ stream_reset(demuxer->stream);
+ stream_seek(demuxer->stream, orig_pos);
+ return 0;
+}
demuxer_t* demux_open_nuv ( demuxer_t* demuxer )
{
@@ -282,6 +389,13 @@
sh_audio->wf->cbSize = 0;
}
+ /* Check for extended data (X frame) and read settings from it */
+ if (!demux_xscan_nuv(demuxer, rtjpeg_fileheader.width,
+ rtjpeg_fileheader.height))
+ /* Otherwise assume defaults */
+ mp_msg(MSGT_DEMUXER, MSGL_V, "No NUV extended frame, using defaults\n");
+
+
priv->index_list = (nuv_position_t*) malloc(sizeof(nuv_position_t));
priv->index_list->frame = 0;
priv->index_list->time = 0;
@@ -304,9 +418,12 @@
if(stream_read(demuxer->stream,(char*)&ns,sizeof(ns)) != sizeof(ns))
return 0;
- if ( strncmp ( ns.finfo, "NuppelVideo", 12 ) )
+ if ( strncmp ( ns.finfo, "NuppelVideo", 12 ) &&
+ strncmp ( ns.finfo, "MythTVVideo", 12 ) )
return 0; /* Not a NuppelVideo file */
- if ( strncmp ( ns.version, "0.05", 5 ) )
+ if ( strncmp ( ns.version, "0.05", 5 ) &&
+ strncmp ( ns.version, "0.06", 5 ) &&
+ strncmp ( ns.version, "0.07", 5 ) )
return 0; /* Wrong version NuppelVideo file */
/* Return to original position */
Index: libmpdemux/nuppelvideo.h
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdemux/nuppelvideo.h,v
retrieving revision 1.4
diff -u -r1.4 nuppelvideo.h
--- libmpdemux/nuppelvideo.h 13 Jul 2005 17:24:42 -0000 1.4
+++ libmpdemux/nuppelvideo.h 28 Jul 2005 17:14:06 -0000
@@ -71,6 +71,34 @@
// R: do not use here! (fixed 'RTjjjjjjjjjjjjjj')
} rtframeheader;
+/* for MythTV */
+typedef struct __attribute__((packed)) extendeddata
+{
+ int version; // yes, this is repeated from the file header
+ int video_fourcc; // video encoding method used
+ int audio_fourcc; // audio encoding method used
+ // generic data
+ int audio_sample_rate;
+ int audio_bits_per_sample;
+ int audio_channels;
+ // codec specific
+ // mp3lame
+ int audio_compression_ratio;
+ int audio_quality;
+ // rtjpeg
+ int rtjpeg_quality;
+ int rtjpeg_luma_filter;
+ int rtjpeg_chroma_filter;
+ // libavcodec
+ int lavc_bitrate;
+ int lavc_qmin;
+ int lavc_qmax;
+ int lavc_maxqdiff;
+ // unused for later -- total size of 128 integers.
+ // new fields must be added at the end, above this comment.
+ int expansion[113];
+} extendeddata;
+
#define FRAMEHEADERSIZE sizeof(rtframeheader)
#define FILEHEADERSIZE sizeof(rtfileheader)
@@ -108,4 +136,21 @@
(h)->timecode = le2me_32((h)->timecode); \
(h)->packetlength = le2me_32((h)->packetlength); \
}
+#define le2me_extendeddata(h) { \
+ (h)->version = le2me_32((h)->version); \
+ (h)->video_fourcc = le2me_32((h)->video_fourcc); \
+ (h)->audio_fourcc = le2me_32((h)->audio_fourcc); \
+ (h)->audio_sample_rate = le2me_32((h)->audio_sample_rate); \
+ (h)->audio_bits_per_sample = le2me_32((h)->audio_bits_per_sample);\
+ (h)->audio_channels = le2me_32((h)->audio_channels); \
+ (h)->audio_compression_ratio = le2me_32((h)->audio_compression_ratio);\
+ (h)->audio_quality = le2me_32((h)->audio_quality); \
+ (h)->rtjpeg_quality = le2me_32((h)->rtjpeg_quality); \
+ (h)->rtjpeg_luma_filter = le2me_32((h)->rtjpeg_luma_filter); \
+ (h)->rtjpeg_chroma_filter = le2me_32((h)->rtjpeg_chroma_filter);\
+ (h)->lavc_bitrate = le2me_32((h)->lavc_bitrate); \
+ (h)->lavc_qmin = le2me_32((h)->lavc_qmin); \
+ (h)->lavc_qmax = le2me_32((h)->lavc_qmax); \
+ (h)->lavc_maxqdiff = le2me_32((h)->lavc_maxqdiff); \
+ }
More information about the MPlayer-dev-eng
mailing list