Media add-on for DVB.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20707 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Marcus Overhagen 2007-04-15 18:42:03 +00:00
parent fbaad6fdb5
commit b2859abe13
20 changed files with 5178 additions and 0 deletions

View File

@ -0,0 +1,292 @@
/*
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h> // required on BeOS R5
#include <OS.h>
#include "DVBCard.h"
DVBCard::DVBCard(const char *path)
: fInitStatus(B_OK)
, fDev(-1)
{
printf("DVBCard opening %s\n", path);
fDev = open(path, O_RDWR);
if (fDev < 0) {
printf("DVBCard opening %s failed\n", path);
fInitStatus = B_ERROR;
return;
}
dvb_frequency_info_t info;
if (do_ioctl(fDev, DVB_GET_FREQUENCY_INFO, &info) < 0) {
printf("DVB_GET_FREQUENCY_INFO failed with error %s\n", strerror(errno));
// close(fDev);
// fDev = -1;
// return;
}
fFreqMin = info.frequency_min;
fFreqMax = info.frequency_max;
fFreqStep = info.frequency_step;
fCaptureActive = false;
}
DVBCard::~DVBCard()
{
if (fDev > 0)
close(fDev);
}
status_t
DVBCard::InitCheck()
{
return fInitStatus;
}
status_t
DVBCard::GetCardType(dvb_type_t *type)
{
dvb_interface_info_t info;
if (do_ioctl(fDev, DVB_GET_INTERFACE_INFO, &info) < 0) {
printf("DVB_GET_INTERFACE_INFO failed with error %s\n", strerror(errno));
return errno;
}
if (info.version < 1) {
printf("DVBCard::GetCardInfo wrong API version\n");
return B_ERROR;
}
*type = info.type;
return B_OK;
}
status_t
DVBCard::GetCardInfo(char *_name, int max_name_len, char *_info, int max_info_len)
{
dvb_interface_info_t info;
if (do_ioctl(fDev, DVB_GET_INTERFACE_INFO, &info) < 0) {
printf("DVB_GET_INTERFACE_INFO failed with error %s\n", strerror(errno));
return errno;
}
// strlcpy(_name, info.name, max_name_len);
// strlcpy(_info, info.info, max_info_len);
strcpy(_name, info.name);
strcpy(_info, info.info);
if (info.version < 1) {
printf("DVBCard::GetCardInfo wrong API version\n");
return B_ERROR;
}
return B_OK;
}
status_t
DVBCard::SetTuningParameter(const dvb_tuning_parameters_t& param)
{
if (fDev < 0)
return B_NO_INIT;
printf("DVBCard::SetTuningParameter:\n");
/*
printf("frequency %Ld\n", param.frequency);
printf("inversion %d\n", param.inversion);
printf("bandwidth %d\n", param.bandwidth);
printf("modulation %d\n", param.modulation);
printf("hierarchy %d\n", param.hierarchy);
printf("code_rate_hp %d\n", param.code_rate_hp);
printf("code_rate_lp %d\n", param.code_rate_lp);
printf("transmission_mode %d\n", param.transmission_mode);
printf("guard_interval %d\n", param.guard_interval);
printf("symbolrate %d\n", param.symbolrate);
printf("polarity %d\n", param.polarity);
printf("agc_inversion %d\n", param.agc_inversion);
*/
params = param;// XXX temporary!
// if (do_ioctl(fDev, DVB_SET_TUNING_PARAMETERS, const_cast<void *>(&param)) < 0) {
// if (do_ioctl(fDev, DVB_SET_TUNING_PARAMETERS, (void *)(&param)) < 0) {
if (ioctl(fDev, DVB_SET_TUNING_PARAMETERS, (void *)(&param)) < 0) {
printf("DVB_SET_TUNING_PARAMETERS failed with error %s\n", strerror(errno));
return errno;
}
dvb_status_t status;
bigtime_t start = system_time();
bool has_lock = false;
bool has_signal = false;
bool has_carrier = false;
do {
if (do_ioctl(fDev, DVB_GET_STATUS, &status) < 0) {
printf("DVB_GET_STATUS failed with error %s\n", strerror(errno));
return errno;
}
if (!has_signal && status & DVB_STATUS_SIGNAL) {
has_signal = true;
printf("got signal after %.6f\n", (system_time() - start) / 1e6);
}
if (!has_carrier && status & DVB_STATUS_CARRIER) {
has_carrier = true;
printf("got carrier after %.6f\n", (system_time() - start) / 1e6);
}
if (!has_lock && status & DVB_STATUS_LOCK) {
has_lock = true;
printf("got lock after %.6f\n", (system_time() - start) / 1e6);
}
if ((status & (DVB_STATUS_SIGNAL|DVB_STATUS_CARRIER|DVB_STATUS_LOCK)) == (DVB_STATUS_SIGNAL|DVB_STATUS_CARRIER|DVB_STATUS_LOCK))
break;
snooze(25000);
} while ((system_time() - start) < 5000000);
if ((status & (DVB_STATUS_SIGNAL|DVB_STATUS_CARRIER|DVB_STATUS_LOCK)) != (DVB_STATUS_SIGNAL|DVB_STATUS_CARRIER|DVB_STATUS_LOCK)) {
printf("DVB tuning failed! need these status flags: DVB_STATUS_SIGNAL, DVB_STATUS_CARRIER, DVB_STATUS_LOCK\n");
return B_ERROR;
}
return B_OK;
}
status_t
DVBCard::GetTuningParameter(dvb_tuning_parameters_t *param)
{
// XXX get from CARD
*param = params;
return B_OK;
}
status_t
DVBCard::GetSignalInfo(uint32 *ss, uint32 *ber, uint32 *snr)
{
if (do_ioctl(fDev, DVB_GET_SS, ss) < 0) {
printf("DVB_GET_SS failed with error %s\n", strerror(errno));
return errno;
}
if (do_ioctl(fDev, DVB_GET_BER, ber) < 0) {
printf("DVB_GET_BER failed with error %s\n", strerror(errno));
return errno;
}
if (do_ioctl(fDev, DVB_GET_SNR, snr) < 0) {
printf("DVB_GET_SNR failed with error %s\n", strerror(errno));
return errno;
}
printf("ss %08lx, ber %08lx, snr %08lx\n", *ss, *ber, *snr);
printf("ss %lu%%, ber %lu%%, snr %lu%%\n", *ss / (0xffffffff / 100), *ber / (0xffffffff / 100), *snr / (0xffffffff / 100));
return B_OK;
}
status_t
DVBCard::CaptureStart()
{
printf("DVBCard::CaptureStart\n");
if (fCaptureActive) {
printf("CaptureStart already called, doing nothing\n");
return B_OK;
}
if (do_ioctl(fDev, DVB_START_CAPTURE, 0) < 0) {
printf("DVB_START_CAPTURE failed with error %s\n", strerror(errno));
return errno;
}
fCaptureActive = true;
return B_OK;
}
status_t
DVBCard::CaptureStop()
{
printf("DVBCard::CaptureStop\n");
if (!fCaptureActive) {
printf("CaptureStop already called, doing nothing\n");
return B_OK;
}
if (do_ioctl(fDev, DVB_STOP_CAPTURE, 0) < 0) {
printf("DVB_STOP_CAPTURE failed with error %s\n", strerror(errno));
return errno;
}
fCaptureActive = false;
return B_OK;
}
status_t
DVBCard::Capture(void **data, size_t *size, bigtime_t *end_time)
{
dvb_capture_t cap;
if (ioctl(fDev, DVB_CAPTURE, &cap) < 0)
return errno;
*data = cap.data;
*size = cap.size;
*end_time = cap.end_time;
return B_OK;
}
int
DVBCard::do_ioctl(int fDev, ulong op, void *arg)
{
int res = 0; // silence stupid compiler warning
int i;
for (i = 0; i < 20; i++) {
res = ioctl(fDev, op, arg);
if (res >= 0)
break;
}
if (i != 0) printf("ioctl %lx repeated %d times\n", op, i);
return res;
}

View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __DVB_CARD_H
#define __DVB_CARD_H
#include "../drivers/cx23882/dvb.h"
class DVBCard
{
public:
DVBCard(const char *path);
~DVBCard();
status_t InitCheck();
status_t GetCardType(dvb_type_t *type);
status_t GetCardInfo(char *name, int max_name_len, char *info, int max_info_len);
status_t GetSignalInfo(uint32 *ss, uint32 *ber, uint32 *snr);
status_t SetTuningParameter(const dvb_tuning_parameters_t& param);
status_t GetTuningParameter(dvb_tuning_parameters_t *param);
status_t CaptureStart();
status_t CaptureStop();
status_t Capture(void **data, size_t *size, bigtime_t *end_time);
private:
int do_ioctl(int fDev, ulong op, void *arg);
status_t fInitStatus;
int fDev;
int64 fFreqMin;
int64 fFreqMax;
int64 fFreqStep;
bool fCaptureActive;
dvb_tuning_parameters_t params; // XXX temporary cache
};
#endif

View File

@ -0,0 +1,277 @@
/*
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "DVBMediaAddon.h"
#include "DVBCard.h"
#include "DVBMediaNode.h"
#include "config.h"
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <Alert.h>
#include <Directory.h>
#include <Entry.h>
#include <Path.h>
struct device_info
{
DVBCard * card;
char name[200];
char info[200];
media_format formats[5];
flavor_info flavor;
bool active; // workaround for zeta
};
extern "C" BMediaAddOn *
make_media_addon(image_id id)
{
return new DVBMediaAddon(id);
}
DVBMediaAddon::DVBMediaAddon(image_id id)
: BMediaAddOn(id)
{
ScanFolder("/dev/dvb");
}
DVBMediaAddon::~DVBMediaAddon()
{
FreeDeviceList();
}
status_t
DVBMediaAddon::InitCheck(const char ** out_failure_text)
{
if (!fDeviceList.CountItems()) {
*out_failure_text = "No supported device found";
return B_ERROR;
}
return B_OK;
}
int32
DVBMediaAddon::CountFlavors()
{
return fDeviceList.CountItems();
}
status_t
DVBMediaAddon::GetFlavorAt(int32 n, const flavor_info ** out_info)
{
device_info *dev = (device_info *)fDeviceList.ItemAt(n);
if (!dev)
return B_ERROR;
*out_info = &dev->flavor;
return B_OK;
}
BMediaNode *
DVBMediaAddon::InstantiateNodeFor(const flavor_info * info, BMessage * config, status_t * out_error)
{
printf("DVB: DVBMediaAddon::InstantiateNodeFor\n");
device_info *dev = (device_info *)fDeviceList.ItemAt(info->internal_id);
if (!dev || dev->flavor.internal_id != info->internal_id) {
*out_error = B_ERROR;
return NULL;
}
*out_error = B_OK;
// workaround for Zeta
if (dev->active) {
printf("DVB: max instances violation!!!\n");
*out_error = B_ERROR;
return NULL;
} else {
dev->active = true;
}
return new DVBMediaNode(this, dev->name, dev->flavor.internal_id, dev->card, &dev->active);
}
bool
DVBMediaAddon::WantsAutoStart()
{
#if BUILD_FOR_HAIKU
printf("DVB: DVBMediaAddon::WantsAutoStart - NO\n");
return false;
#else
printf("DVB: DVBMediaAddon::WantsAutoStart - YES\n");
return true;
#endif
}
status_t
DVBMediaAddon::AutoStart(int index, BMediaNode **outNode, int32 *outInternalID, bool *outHasMore)
{
printf("DVB: DVBMediaAddon::AutoStart, index %d\n", index);
#if BUILD_FOR_HAIKU
return B_ERROR;
#else
device_info *dev = (device_info *)fDeviceList.ItemAt(index);
if (!dev) {
printf("DVB: DVBMediaAddon::AutoStart, bad index\n");
return B_BAD_INDEX;
}
*outHasMore = fDeviceList.ItemAt(index + 1) ? true : false;
// workaround for Zeta
if (dev->active) {
printf("DVB: max instances violation!!!\n");
*outInternalID = -1;
*outNode = NULL;
return B_MEDIA_ADDON_FAILED;
}
dev->active = true;
*outInternalID = dev->flavor.internal_id;
*outNode = new DVBMediaNode(this, dev->name, dev->flavor.internal_id, dev->card, &dev->active);
printf("DVB: DVBMediaAddon::AutoStart, success\n");
return B_OK;
#endif
}
void
DVBMediaAddon::ScanFolder(const char *path)
{
BDirectory dir(path);
if (dir.InitCheck() != B_OK)
return;
BEntry ent;
while (dir.GetNextEntry(&ent) == B_OK) {
BPath path(&ent);
if (ent.IsDirectory()) {
ScanFolder(path.Path());
} else {
DVBCard *card = new DVBCard(path.Path());
if (card->InitCheck() == B_OK)
AddDevice(card, path.Path());
else
delete card;
}
}
}
void
DVBMediaAddon::AddDevice(DVBCard *card, const char *path)
{
dvb_type_t type;
char name[250];
char info[1000];
const char *dvbtype;
const char *dvbnumber;
// get card name, info and type
if (B_OK != card->GetCardType(&type)) {
printf("DVBMediaAddon::AddDevice: getting DVB card type failed\n");
return;
}
if (B_OK != card->GetCardInfo(name, sizeof(name), info, sizeof(info))) {
printf("DVBMediaAddon::AddDevice: getting DVB card info failed\n");
return;
}
// get type
switch (type) {
case DVB_TYPE_DVB_C: dvbtype = "C"; break;
case DVB_TYPE_DVB_H: dvbtype = "H"; break;
case DVB_TYPE_DVB_S: dvbtype = "S"; break;
case DVB_TYPE_DVB_T: dvbtype = "T"; break;
default:
printf("DVBMediaAddon::AddDevice: unsupported DVB type %d\n", type);
return;
}
// get interface number
const char *p = strrchr(path, '/');
dvbnumber = p ? p + 1 : "";
// create device_info
device_info *dev = new device_info;
fDeviceList.AddItem(dev);
dev->card = card;
dev->active = false; // workaround for Zeta
// setup name and info, it's important that name starts with "DVB"
// snprintf(dev->name, sizeof(dev->name), "DVB-%s %s (%s)", dvbtype, dvbnumber, name);
// strlcpy(dev->info, info, sizeof(dev->info));
sprintf(dev->name, "DVB-%s %s %s", dvbtype, name, dvbnumber);
strcpy(dev->info, info);
// setup supported formats (the lazy way)
memset(dev->formats, 0, sizeof(dev->formats));
dev->formats[0].type = B_MEDIA_RAW_VIDEO;
dev->formats[1].type = B_MEDIA_RAW_AUDIO;
dev->formats[2].type = B_MEDIA_ENCODED_VIDEO;
dev->formats[3].type = B_MEDIA_ENCODED_AUDIO;
dev->formats[4].type = B_MEDIA_MULTISTREAM;
// setup flavor info
dev->flavor.name = dev->name;
dev->flavor.info = dev->info;
dev->flavor.kinds = B_BUFFER_PRODUCER | B_CONTROLLABLE | B_PHYSICAL_INPUT;
dev->flavor.flavor_flags = B_FLAVOR_IS_GLOBAL;
dev->flavor.internal_id = fDeviceList.CountItems() - 1;
dev->flavor.possible_count = 1;
dev->flavor.in_format_count = 0;
dev->flavor.in_format_flags = 0;
dev->flavor.in_formats = 0;
dev->flavor.out_format_count = 5;
dev->flavor.out_format_flags = 0;
dev->flavor.out_formats = dev->formats;
}
void
DVBMediaAddon::FreeDeviceList()
{
device_info *dev;
while ((dev = (device_info *)fDeviceList.RemoveItem((int32)0))) {
delete dev->card;
delete dev;
}
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _DVB_MEDIA_ADDON_H_
#define _DVB_MEDIA_ADDON_H_
#include <MediaAddOn.h>
class DVBCard;
class DVBMediaAddon : public BMediaAddOn
{
public:
DVBMediaAddon(image_id id);
~DVBMediaAddon();
status_t InitCheck(const char **out_failure_text);
int32 CountFlavors();
status_t GetFlavorAt(int32 n, const flavor_info **out_info);
BMediaNode *InstantiateNodeFor(const flavor_info *info, BMessage *config, status_t *out_error);
bool WantsAutoStart();
status_t AutoStart(int index, BMediaNode **outNode, int32 *outInternalID, bool *outHasMore);
protected:
void ScanFolder(const char *path);
void AddDevice(DVBCard *card, const char *path);
void FreeDeviceList();
protected:
BList fDeviceList;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,306 @@
/*
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __DVB_MEDIA_NODE_H
#define __DVB_MEDIA_NODE_H
#include <kernel/OS.h>
#include <media/BufferProducer.h>
#include <media/Controllable.h>
#include <media/MediaDefs.h>
#include <media/MediaEventLooper.h>
#include <media/MediaNode.h>
#include <support/Locker.h>
#include "ts_demux.h"
#include "DVBCard.h"
#include "StringList.h"
#include "DecoderInterface.h"
class BDiscreteParameter;
class PacketQueue;
class DVBCard;
class DVBMediaNode :
public virtual BBufferProducer,
public virtual BControllable,
public virtual BMediaEventLooper
{
public:
DVBMediaNode(BMediaAddOn *addon,
const char *name, int32 internal_id, DVBCard *card, bool *active); // bool *active is a workaround for Zeta
virtual ~DVBMediaNode();
virtual status_t InitCheck() const { return fInitStatus; }
/* BMediaNode */
public:
virtual BMediaAddOn *AddOn(int32 * internal_id) const;
virtual status_t HandleMessage(int32 message, const void *data,
size_t size);
protected:
virtual void Preroll();
virtual void SetTimeSource(BTimeSource * time_source);
virtual void SetRunMode(run_mode mode);
/* BMediaEventLooper */
protected:
virtual void NodeRegistered();
virtual void Stop(bigtime_t performance_time, bool immediate);
virtual void HandleEvent(const media_timed_event *event,
bigtime_t lateness, bool realTimeEvent = false);
/* BBufferProducer */
protected:
virtual status_t FormatSuggestionRequested(media_type type, int32 quality,
media_format * format);
virtual status_t FormatProposal(const media_source &source,
media_format *format);
virtual status_t FormatChangeRequested(const media_source &source,
const media_destination &destination,
media_format *io_format, int32 *_deprecated_);
virtual status_t GetNextOutput(int32 * cookie, media_output * out_output);
virtual status_t DisposeOutputCookie(int32 cookie);
virtual status_t SetBufferGroup(const media_source &for_source,
BBufferGroup * group);
virtual status_t VideoClippingChanged(const media_source &for_source,
int16 num_shorts, int16 *clip_data,
const media_video_display_info &display,
int32 * _deprecated_);
virtual status_t GetLatency(bigtime_t * out_latency);
virtual status_t PrepareToConnect(const media_source &what,
const media_destination &where,
media_format *format,
media_source *out_source, char *out_name);
virtual void Connect(status_t error, const media_source &source,
const media_destination &destination,
const media_format & format, char *io_name);
virtual void Disconnect(const media_source & what,
const media_destination & where);
virtual void LateNoticeReceived(const media_source & what,
bigtime_t how_much, bigtime_t performance_time);
virtual void EnableOutput(const media_source & what, bool enabled,
int32 * _deprecated_);
virtual status_t SetPlayRate(int32 numer,int32 denom);
virtual void AdditionalBufferRequested(const media_source & source,
media_buffer_id prev_buffer, bigtime_t prev_time,
const media_seek_tag * prev_tag);
virtual void LatencyChanged(const media_source & source,
const media_destination & destination,
bigtime_t new_latency, uint32 flags);
/* BControllable */
protected:
virtual status_t GetParameterValue(int32 id, bigtime_t *last_change,
void *value, size_t *size);
virtual void SetParameterValue(int32 id, bigtime_t when,
const void *value, size_t size);
/* state */
private:
void HandleStart(bigtime_t performance_time);
void HandleStop();
void HandleTimeWarp(bigtime_t performance_time);
void HandleSeek(bigtime_t performance_time);
void InitDefaultFormats();
void SpecializeFormatRawVideo(media_raw_video_format *format);
void SpecializeFormatRawAudio(media_multi_audio_format *format);
void SpecializeFormatEncVideo(media_encoded_video_format *format);
void SpecializeFormatEncAudio(media_encoded_audio_format *format);
void SpecializeFormatTS(media_multistream_format *format);
bool VerifyFormatRawVideo(const media_raw_video_format &format);
bool VerifyFormatRawAudio(const media_multi_audio_format &format);
status_t GetStreamFormat(PacketQueue *queue, media_format *format);
status_t SetOutput(const media_source &source, const media_destination &destination, const media_format &format);
status_t ResetOutput(const media_source &source);
const char * SourceDefaultName(const media_source &source);
BParameterWeb * CreateParameterWeb();
void SetAboutInfo(BParameterGroup *about);
void RefreshParameterWeb();
void LoadSettings();
void LoadAddons();
void UnloadAddons();
image_id LoadAddon(const char *path, const char *name, void **ptr);
void AddStateItems(BDiscreteParameter *param);
void AddRegionItems(BDiscreteParameter *param);
void AddChannelItems(BDiscreteParameter *param);
void AddAudioItems(BDiscreteParameter *param);
void RefreshStateList();
void RefreshRegionList();
void RefreshChannelList();
void RefreshAudioList();
status_t StartCapture();
status_t StopCapture();
status_t StartCaptureThreads();
status_t StopCaptureThreads();
status_t Tune();
status_t ExtractTuningParams(const char *description, int audio_pid_index,
dvb_tuning_parameters_t *param,
int *video_pid, int *audio_pid, int *pcr_pid);
static int32 _card_reader_thread_(void *arg);
static int32 _mpeg_demux_thread_(void *arg);
static int32 _enc_audio_thread_(void *arg);
static int32 _enc_video_thread_(void *arg);
static int32 _mpeg_ts_thread_(void *arg);
static int32 _raw_audio_thread_(void *arg);
static int32 _raw_video_thread_(void *arg);
void card_reader_thread();
void mpeg_demux_thread();
void enc_audio_thread();
void enc_video_thread();
void mpeg_ts_thread();
void raw_audio_thread();
void raw_video_thread();
status_t GetNextVideoChunk(const void **chunkData, size_t *chunkLen, media_header *mh);
status_t GetNextAudioChunk(const void **chunkData, size_t *chunkLen, media_header *mh);
static status_t _GetNextVideoChunk(const void **chunkData, size_t *chunkLen, media_header *mh, void *cookie);
static status_t _GetNextAudioChunk(const void **chunkData, size_t *chunkLen, media_header *mh, void *cookie);
status_t fInitStatus;
int32 fInternalID;
BMediaAddOn *fAddOn;
bool fStopDisabled;
bool fOutputEnabledRawVideo;
bool fOutputEnabledRawAudio;
bool fOutputEnabledEncVideo;
bool fOutputEnabledEncAudio;
bool fOutputEnabledTS;
media_output fOutputRawVideo;
media_output fOutputRawAudio;
media_output fOutputEncVideo;
media_output fOutputEncAudio;
media_output fOutputTS;
media_format fDefaultFormatRawVideo;
media_format fDefaultFormatRawAudio;
media_format fDefaultFormatEncVideo;
media_format fDefaultFormatEncAudio;
media_format fDefaultFormatTS;
media_format fRequiredFormatRawVideo;
media_format fRequiredFormatRawAudio;
media_format fRequiredFormatEncVideo;
media_format fRequiredFormatEncAudio;
media_format fRequiredFormatTS;
PacketQueue * fCardDataQueue; // holds MPEG TS data read from the card
PacketQueue * fRawVideoQueue; // holds encoded PES frames for video decoding
PacketQueue * fRawAudioQueue; // holds encoded PES frames for audio decoding
PacketQueue * fEncVideoQueue; // holds encoded PES frames for enc video out
PacketQueue * fEncAudioQueue; // holds encoded PES frames for enc audio out
PacketQueue * fMpegTsQueue; // holds encoded PES frames for MPEG TS out
DVBCard * fCard;
bool fCaptureThreadsActive;
thread_id fThreadIdCardReader;
thread_id fThreadIdMpegDemux;
thread_id fThreadIdRawAudio;
thread_id fThreadIdRawVideo;
thread_id fThreadIdEncAudio;
thread_id fThreadIdEncVideo;
thread_id fThreadIdMpegTS;
volatile bool fTerminateThreads;
TSDemux * fDemux;
BBufferGroup * fBufferGroupRawVideo;
BBufferGroup * fBufferGroupRawAudio;
BParameterWeb * fWeb;
dvb_tuning_parameters_t fTuningParam;
dvb_type_t fInterfaceType;
int fAudioPid;
int fVideoPid;
int fPcrPid;
bool fTuningSuccess;
bool fCaptureActive;
sem_id fVideoDelaySem;
sem_id fAudioDelaySem;
int fSelectedState;
int fSelectedRegion;
int fSelectedChannel;
int fSelectedAudio;
StringList * fStateList;
StringList * fRegionList;
StringList * fChannelList;
StringList * fAudioList;
DecoderInterface * fVideoDecoder;
DecoderInterface * fAudioDecoder;
Packet * fCurrentVideoPacket;
Packet * fCurrentAudioPacket;
image_id fMpeg2VideoDecoderImage;
image_id fMpeg2AudioDecoderImage;
image_id fAC3DecoderImage;
image_id fDeinterlaceFilterImage;
DecoderInterface * (*instantiate_mpeg2_video_decoder)(get_next_chunk_func, void *, const char *);
DecoderInterface * (*instantiate_mpeg2_audio_decoder)(get_next_chunk_func, void *, const char *);
DecoderInterface * (*instantiate_ac3_audio_decoder)(get_next_chunk_func, void *, const char *);
DecoderInterface * (*instantiate_deinterlace_filter)(get_next_chunk_func, void *, const char *);
BLocker lock;
bool * fActive; // workaround for Zeta
// used only for debugging:
int fVideoFile;
int fAudioFile;
int fRawAudioFile;
};
#endif

View File

@ -0,0 +1,108 @@
/*
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <media/MediaFormats.h>
#include <stdio.h>
#include "MediaFormat.h"
void
PrintFormat(const media_output &output)
{
PrintFormat(output.format);
}
void
PrintFormat(const media_format &format)
{
char s[200];
string_for_format(format, s, sizeof(s));
printf("%s\n", s);
}
status_t
GetHeaderFormat(media_format *out_format, const void *header, size_t size, int stream_id)
{
const uint8 *d = (const uint8 *)header;
printf("GetHeaderFormat: stream_id %02x\n", stream_id);
printf("frame header: "
"%02x %02x %02x %02x %02x %02x %02x %02x "
"%02x %02x %02x %02x %02x %02x %02x %02x\n",
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
if (d[0] == 0xff && d[1] == 0xfc) {
printf("GetHeaderFormat: assuming mepeg audio\n");
status_t err;
media_format_description desc;
desc.family = B_MPEG_FORMAT_FAMILY;
desc.u.mpeg.id = B_MPEG_1_AUDIO_LAYER_3;
BMediaFormats formats;
media_format format;
err = formats.InitCheck();
if (err)
return err;
err = formats.GetFormatFor(desc, out_format);
if (err)
return err;
out_format->u.encoded_audio.output.frame_rate = 48000;
out_format->u.encoded_audio.output.channel_count = 2;
out_format->u.encoded_audio.output.buffer_size = 1024;
printf("GetHeaderFormat: ");
PrintFormat(*out_format);
} else {
printf("GetHeaderFormat: assuming mepeg video\n");
status_t err;
media_format_description desc;
desc.family = B_MPEG_FORMAT_FAMILY;
desc.u.mpeg.id = B_MPEG_1_VIDEO;
BMediaFormats formats;
media_format format;
err = formats.InitCheck();
if (err)
return err;
err = formats.GetFormatFor(desc, out_format);
if (err)
return err;
}
return B_OK;
}

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __MEDIA_FORMAT_H
#define __MEDIA_FORMAT_H
class media_output;
class media_format;
void PrintFormat(const media_output &output);
void PrintFormat(const media_format &format);
status_t GetHeaderFormat(media_format *out_format, const void *header, size_t size, int stream_id);
#endif

View File

@ -0,0 +1,86 @@
/*
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "packet.h"
#define PACKET
#ifdef PACKET
#define TRACE printf
#else
#define TRACE(a...)
#endif
Packet::Packet(size_t init_size)
: fBuffer(malloc(init_size))
, fBufferSize(0)
, fBufferSizeMax(init_size)
, fTimeStamp(0)
{
}
Packet::Packet(const Packet &clone)
{
fBufferSize = clone.Size();
fBufferSizeMax = fBufferSize;
fBuffer = malloc(fBufferSize);
fTimeStamp = clone.TimeStamp();
memcpy(fBuffer, clone.Data(), fBufferSize);
}
Packet::Packet(const void *data, size_t size, bigtime_t time_stamp)
: fBuffer(malloc(size))
, fBufferSize(size)
, fBufferSizeMax(size)
, fTimeStamp(time_stamp)
{
memcpy(fBuffer, data, size);
}
Packet::~Packet()
{
free(fBuffer);
}
void
Packet::AddData(const void *data, size_t size)
{
if (fBufferSize + size > fBufferSizeMax) {
fBufferSizeMax = (fBufferSize + size + 8191) & ~8191;
fBuffer = realloc(fBuffer, fBufferSizeMax);
}
memcpy((char *)fBuffer + fBufferSize, data, size);
fBufferSize += size;
}

View File

@ -0,0 +1,97 @@
/*
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __PACKET_H
#define __PACKET_H
#include <SupportDefs.h>
class Packet
{
public:
Packet(size_t init_size = 8192);
Packet(const Packet &clone);
Packet(const void *data, size_t size, bigtime_t time_stamp = 0);
~Packet();
void AddData(const void *data, size_t size);
void MakeEmpty();
const uint8 * Data() const;
size_t Size() const;
void SetTimeStamp(bigtime_t time_stamp);
bigtime_t TimeStamp() const;
private:
// not implemented
Packet & operator= (const Packet &clone);
private:
void * fBuffer;
size_t fBufferSize;
size_t fBufferSizeMax;
bigtime_t fTimeStamp;
};
inline const uint8 *
Packet::Data() const
{
return (uint8 *)fBuffer;
}
inline size_t
Packet::Size() const
{
return fBufferSize;
}
inline void
Packet::SetTimeStamp(bigtime_t time_stamp)
{
fTimeStamp = time_stamp;
}
inline bigtime_t
Packet::TimeStamp() const
{
return fTimeStamp;
}
inline void
Packet::MakeEmpty()
{
fBufferSize = 0;
fTimeStamp = 0;
}
#endif

View File

@ -0,0 +1,162 @@
/*
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <OS.h>
#include "Packet.h"
#include "PacketQueue.h"
#define TRACE_PACKET_QUEUE
#ifdef TRACE_PACKET_QUEUE
#define TRACE printf
#else
#define TRACE(a...)
#endif
PacketQueue::PacketQueue(int max_packets)
: fQueue(new Packet* [max_packets])
, fSem(create_sem(0, "packet queue sem"))
, fTerminate(false)
, fWriteIndex(0)
, fReadIndex(0)
, fMaxPackets(max_packets)
, fPacketCount(0)
{
}
PacketQueue::~PacketQueue()
{
Empty();
delete_sem(fSem);
delete [] fQueue;
}
void
PacketQueue::Empty()
{
while (fPacketCount--) {
delete fQueue[fReadIndex];
fReadIndex = (fReadIndex + 1) % fMaxPackets;
}
}
status_t
PacketQueue::Insert(Packet *packet)
{
if (fTerminate) {
return B_NOT_ALLOWED;
}
if (atomic_add(&fPacketCount, 1) == fMaxPackets) {
atomic_add(&fPacketCount, -1);
return B_WOULD_BLOCK;
}
fQueue[fWriteIndex] = packet;
fWriteIndex = (fWriteIndex + 1) % fMaxPackets;
release_sem(fSem);
return B_OK;
}
status_t
PacketQueue::Remove(Packet **packet)
{
if (fTerminate) {
return B_NOT_ALLOWED;
}
if (acquire_sem(fSem) != B_OK)
return B_ERROR;
if (fTerminate) {
return B_NOT_ALLOWED;
}
*packet = fQueue[fReadIndex];
atomic_add(&fPacketCount, -1);
fReadIndex = (fReadIndex + 1) % fMaxPackets;
return B_OK;
}
void
PacketQueue::Flush(bigtime_t timeout)
{
if (fTerminate) {
return;
}
timeout += system_time();
while (acquire_sem_etc(fSem, 1, B_ABSOLUTE_TIMEOUT, timeout) == B_OK) {
if (fTerminate) {
return;
}
Packet *packet = fQueue[fReadIndex];
atomic_add(&fPacketCount, -1);
fReadIndex = (fReadIndex + 1) % fMaxPackets;
delete packet;
}
}
// peeks into queue and delivers a copy
status_t
PacketQueue::Peek(Packet **packet)
{
if (fTerminate) {
return B_NOT_ALLOWED;
}
if (acquire_sem(fSem) != B_OK)
return B_ERROR;
if (fTerminate) {
return B_NOT_ALLOWED;
}
*packet = new Packet(*fQueue[fReadIndex]);
release_sem(fSem);
return B_OK;
}
void
PacketQueue::Terminate()
{
fTerminate = true;
release_sem(fSem);
}
void
PacketQueue::Restart()
{
Empty();
delete_sem(fSem);
fSem = create_sem(0, "packet queue sem");
fTerminate = false;
fWriteIndex = 0;
fReadIndex = 0;
fPacketCount = 0;
}

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __PACKET_QUEUE_H
#define __PACKET_QUEUE_H
#include <OS.h>
class Packet;
class PacketQueue
{
public:
PacketQueue(int max_packets = 5);
~PacketQueue();
status_t Insert(Packet *packet);
status_t Remove(Packet **packet);
// peeks into queue and delivers a copy
status_t Peek(Packet **packet);
void Flush(bigtime_t timeout);
void Terminate();
void Restart();
private:
void Empty();
// not implemented
PacketQueue(const PacketQueue & clone);
PacketQueue & operator=(PacketQueue & clone);
private:
Packet **fQueue;
sem_id fSem;
volatile bool fTerminate;
int fWriteIndex;
int fReadIndex;
int fMaxPackets;
int32 fPacketCount;
};
#endif

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __STRING_LIST_H
#define __STRING_LIST_H
#include <List.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
class StringList
{
public:
StringList();
~StringList();
// AddItem makes a copy of the data
void AddItem(const char *string);
// either the String or NULL
const char *ItemAt(int index) const;
void MakeEmpty();
private:
BList list;
};
inline
StringList::StringList()
: list()
{
}
inline
StringList::~StringList()
{
MakeEmpty();
}
inline void
StringList::AddItem(const char *string)
{
list.AddItem(strdup(string));
}
inline const char *
StringList::ItemAt(int index) const
{
return (const char *)list.ItemAt(index);
}
inline void
StringList::MakeEmpty()
{
int i = list.CountItems();
while (--i > -1)
free(list.RemoveItem(i));
}
#endif

View File

@ -0,0 +1,448 @@
/*
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "ts_demux.h"
#include "packet.h"
#include "packet_queue.h"
#define TRACE_TS_DEMUX
#ifdef TRACE_TS_DEMUX
#define TRACE printf
#else
#define TRACE(a...)
#endif
#define CLOCK_TO_USEC(clck) (bigtime_t((clck) + 13) / 27)
#define USEC_TO_CLOCK(usec) (bigtime_t((usec) * 27))
TransportStreamDemux::TransportStreamDemux(
PacketQueue *vid_queue, PacketQueue *aud_queue,
PacketQueue *vid_queue2, PacketQueue *aud_queue2,
PacketQueue *mpeg_ts_queue)
: fCount(0)
, fSystemTime(0)
, fPerformanceTime(0)
, fLastEndTime(0)
, fVidPid(-1)
, fAudPid(-1)
, fPcrPid(-1)
, fVidQueue(vid_queue)
, fVidQueue2(vid_queue2)
, fAudQueue(aud_queue)
, fAudQueue2(aud_queue2)
, fMpegTsQueue(mpeg_ts_queue)
, fVidPacket(new Packet)
, fAudPacket(new Packet)
, fVidPacketValid(false)
, fAudPacketValid(false)
{
}
TransportStreamDemux::~TransportStreamDemux()
{
delete fVidPacket;
delete fAudPacket;
}
void
TransportStreamDemux::SetPIDs(int vid_pid, int aud_pid, int pcr_pid)
{
fVidPacket->MakeEmpty();
fAudPacket->MakeEmpty();
fVidPacketValid = false;
fAudPacketValid = false;
fVidPid = vid_pid;
fAudPid = aud_pid;
fPcrPid = pcr_pid;
}
void
TransportStreamDemux::ProcessPacket(const mpeg_ts_packet *pkt, bigtime_t start_time)
{
fCount++;
// printf("ProcessPacket %Ld\n", fCount);
if (pkt->SyncByte() != 0x47) {
// fCountInvalid++;
printf("packet %Ld sync byte error "
"%02x %02x %02x %02x %02x %02x %02x %02x "
"%02x %02x %02x %02x %02x %02x %02x %02x\n", fCount,
pkt->header[0], pkt->header[1], pkt->header[2], pkt->header[3],
pkt->data[0], pkt->data[1], pkt->data[2], pkt->data[3],
pkt->data[4], pkt->data[5], pkt->data[6], pkt->data[7],
pkt->data[8], pkt->data[9], pkt->data[10], pkt->data[11]);
return;
}
// if (pkt->TransportError()) {
// fCountInvalid++;
// printf("invalid packet %Ld (transport_error_indicator)\n", fCount);
// return;
// }
int pid = pkt->PID();
if (pid == 0) {
ProcessPAT(pkt);
return;
}
if (pid == fPcrPid) {
ProcessPCR(pkt, start_time);
}
if (pid == fAudPid) {
ProcessAUD(pkt);
}
if (pid == fVidPid) {
ProcessVID(pkt);
}
}
void
TransportStreamDemux::ProcessPAT(const mpeg_ts_packet *pkt)
{
}
void
TransportStreamDemux::ProcessPCR(const mpeg_ts_packet *pkt, bigtime_t start_time)
{
if (!(pkt->AdaptationFieldControl() & 0x2)) // adaptation field present?
return;
if (pkt->data[0] < 7) // long enough?
return;
if (!(pkt->data[1] & 0x10)) // PCR present?
return;
int64 pcr;
pcr = (uint64(pkt->data[2]) << 25)
| (uint32(pkt->data[3]) << 17)
| (uint32(pkt->data[4]) << 9)
| (uint32(pkt->data[5]) << 1)
| (pkt->data[6] >> 7);
pcr *= 300;
pcr += (pkt->data[6] & 1) | pkt->data[7];
// printf(" pcr = %Ld\n", pcr);
// bigtime_t now = system_time();
// printf("system_time %.3f, PCR-time %.3f, delta %.06f, PCR %Ld\n", now / 1e6, CLOCK_TO_USEC(pcr) / 1e6, (CLOCK_TO_USEC(pcr) - now) / 1e6, pcr);
// atomic_set64(&fCurrentTime, CLOCK_TO_USEC(pcr));
fTimeSourceLocker.Lock();
fSystemTime = start_time;
fPerformanceTime = CLOCK_TO_USEC(pcr);
fTimeSourceLocker.Unlock();
}
void
TransportStreamDemux::ProcessAUD(const mpeg_ts_packet *pkt)
{
// flush old packet
if (pkt->PayloadUnitStart()) {
if (fAudPacketValid) {
Packet *clone = new Packet(*fAudPacket);
status_t err = fAudQueue->Insert(fAudPacket);
if (err != B_OK) {
delete fAudPacket;
if (err == B_WOULD_BLOCK) {
printf("fAudQueue->Insert failed (would block)\n");
}
}
err = fAudQueue2->Insert(clone);
if (err != B_OK) {
delete clone;
if (err == B_WOULD_BLOCK) {
printf("fAudQueue2->Insert failed (would block)\n");
}
}
fAudPacket = new Packet;
} else {
fAudPacket->MakeEmpty();
fAudPacketValid = true;
}
}
int skip;
switch (pkt->AdaptationFieldControl()) {
case 0: // illegal
skip = 184;
break;
case 1: // payload only
skip = 0;
break;
case 2: // adaptation field only
skip = 184;
break;
case 3: // adaptation field followed by payload
skip = pkt->data[0] + 1;
if (skip > 184)
skip = 184;
break;
default:
skip = 0; // stupid compiler, impossible case
}
const uint8 *data = pkt->data + skip;
int size = 184 - skip;
// if (skip != 0)
// printf("aud skip %d\n", skip);
if (pkt->PayloadUnitStart()) {
if (pkt->TransportError()) {
printf("error in audio packet %02x %02x %02x %02x\n", data[0], data[1], data[2], data[3]);
fAudPacketValid = false;
return;
}
if (data[0] || data[1] || data[2] != 0x01 || data[3] <= 0xbf || data[3] >= 0xf0) {
printf("invalid audio packet %02x %02x %02x %02x\n", data[0], data[1], data[2], data[3]);
fAudPacketValid = false;
return;
}
if (data[7] & 0x80) { // PTS
int64 pts;
int64 dts;
pts = (uint64((data[9] >> 1) & 0x7) << 30)
| (data[10] << 22) | ((data[11] >> 1) << 15)
| (data[12] << 7) | (data[13] >> 1);
pts *= 300;
// printf("vid pts = %Ld\n", pts);
if (data[7] & 0x40) { // DTS
dts = (uint64((data[14] >> 1) & 0x7) << 30)
| (data[15] << 22) | ((data[16] >> 1) << 15)
| (data[17] << 7) | (data[18] >> 1);
dts *= 300;
// printf("aud dts = %Ld\n", dts);
} else {
dts = pts;
}
fAudPacket->SetTimeStamp(CLOCK_TO_USEC(dts));
}
// printf("aud %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
// data[0], data[1], data[2], data[3], data[4],
// data[5], data[6], data[7], data[8], data[9]);
}
fAudPacket->AddData(data, size);
}
void
TransportStreamDemux::ProcessVID(const mpeg_ts_packet *pkt)
{
// flush old packet
// if (pkt->PayloadUnitStart() || pkt->TransportError()) {
if (pkt->PayloadUnitStart()) {
if (fVidPacketValid) {
Packet *clone = new Packet(*fVidPacket);
status_t err = fVidQueue->Insert(fVidPacket);
if (err != B_OK) {
delete fVidPacket;
if (err == B_WOULD_BLOCK) {
printf("fVidQueue->Insert failed (would block)\n");
}
}
err = fVidQueue2->Insert(clone);
if (err != B_OK) {
delete clone;
if (err == B_WOULD_BLOCK) {
printf("fVidQueue2->Insert failed (would block)\n");
}
}
fVidPacket = new Packet;
} else {
fVidPacket->MakeEmpty();
fVidPacketValid = true;
}
}
// if (pkt->TransportError()) {
// printf("transport error\n");
// fVidPacketValid = false;
// return;
// }
int skip;
switch (pkt->AdaptationFieldControl()) {
case 0: // illegal
skip = 184;
break;
case 1: // payload only
skip = 0;
break;
case 2: // adaptation field only
skip = 184;
break;
case 3: // adaptation field followed by payload
skip = pkt->data[0] + 1;
if (skip > 184)
skip = 184;
break;
default:
skip = 0; // stupid compiler, impossible case
}
const uint8 *data = pkt->data + skip;
int size = 184 - skip;
// if (skip != 0)
// printf("vid skip %d\n", skip);
if (pkt->PayloadUnitStart()) {
if (pkt->TransportError()) {
printf("error in video packet %02x %02x %02x %02x\n", data[0], data[1], data[2], data[3]);
fVidPacketValid = false;
return;
}
if (data[0] || data[1] || data[2] != 0x01 || data[3] <= 0xbf || data[3] >= 0xf0) {
printf("invalid video packet %02x %02x %02x %02x\n", data[0], data[1], data[2], data[3]);
fVidPacketValid = false;
return;
}
if (data[7] & 0x80) { // PTS
int64 pts;
int64 dts;
pts = (uint64((data[9] >> 1) & 0x7) << 30)
| (data[10] << 22) | ((data[11] >> 1) << 15)
| (data[12] << 7) | (data[13] >> 1);
pts *= 300;
// printf("vid pts = %Ld\n", pts);
if (data[7] & 0x40) { // DTS
dts = (uint64((data[14] >> 1) & 0x7) << 30)
| (data[15] << 22) | ((data[16] >> 1) << 15)
| (data[17] << 7) | (data[18] >> 1);
dts *= 300;
// printf("vid dts = %Ld\n", dts);
// printf("dts = %Ld, pts = %Ld, delta %Ld ### dts = %Ld, pts = %Ld, delta %Ld\n",
// dts, pts, pts - dts, CLOCK_TO_USEC(dts), CLOCK_TO_USEC(pts), CLOCK_TO_USEC(pts - dts));
} else {
dts = pts;
}
// printf("clocks: dts = %14Ld, pts = %14Ld, delta %8Ld ### usec: dts = %14Ld, pts = %14Ld, delta %8Ld\n",
// dts, pts, pts - dts, CLOCK_TO_USEC(dts), CLOCK_TO_USEC(pts), CLOCK_TO_USEC(pts - dts));
fVidPacket->SetTimeStamp(CLOCK_TO_USEC(dts));
}
// printf("vid %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
// data[0], data[1], data[2], data[3], data[4],
// data[5], data[6], data[7], data[8], data[9]);
}
fVidPacket->AddData(data, size);
}
inline void
TransportStreamDemux::ProcessData(const void *data, int size, bigtime_t start_time, bigtime_t delta)
{
const uint8 *d = (const uint8 *)data;
if (d[0] != 0x47 && size > 376 && d[188] != 0x47 && d[376] != 0x47) {
printf("TransportStreamDemux::ProcessData: input sync error: "
"%02x %02x %02x %02x %02x %02x %02x %02x "
"%02x %02x %02x %02x %02x %02x %02x %02x\n",
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
return;
}
const mpeg_ts_packet *pkt = (const mpeg_ts_packet *)data;
int count = size / 188;
for (int i = 0; i < count; i++) {
ProcessPacket(pkt++, start_time + (i * delta) / count);
}
}
void
TransportStreamDemux::AddData(Packet *packet)
{
bigtime_t end_time = packet->TimeStamp();
if (fLastEndTime == 0) {
#define DEFAULT_DELTA 36270
// need something at the start, 36270 usec is the packet length
// in Germany, and should be ok for other countries, too
fLastEndTime = end_time - DEFAULT_DELTA;
}
bigtime_t delta = end_time - fLastEndTime;
// sanity check
if (delta > (3 * DEFAULT_DELTA)) {
printf("TransportStreamDemux::ProcessData: delta %.6f is too large\n", delta / 1E6);
fLastEndTime = end_time - DEFAULT_DELTA;
delta = DEFAULT_DELTA;
}
ProcessData(packet->Data(), packet->Size(), fLastEndTime, delta);
packet->SetTimeStamp(fLastEndTime);
fLastEndTime = end_time;
status_t err = fMpegTsQueue->Insert(packet);
if (err != B_OK) {
delete packet;
if (err == B_WOULD_BLOCK) {
printf("fMpegTsQueue->Insert failed (would block)\n");
}
}
}

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __TRANSPORT_STREAM_DEMUX_H
#define __TRANSPORT_STREAM_DEMUX_H
#include <Locker.h>
#include "mpeg_ts_packet.h"
class PacketQueue;
class Packet;
class TransportStreamDemux
{
public:
TransportStreamDemux(
PacketQueue *vid_queue, PacketQueue *aud_queue,
PacketQueue *vid_queue2, PacketQueue *aud_queue2,
PacketQueue *mpeg_ts_queue);
virtual ~TransportStreamDemux();
void SetPIDs(int vid_pid, int aud_pid, int pcr_pid);
void AddData(Packet *packet);
void TimesourceInfo(bigtime_t *perf_time, bigtime_t *sys_time);
private:
void ProcessData(const void *data, int size, bigtime_t start_time, bigtime_t delta);
void ProcessPacket(const mpeg_ts_packet *pkt, bigtime_t start_time);
protected:
virtual void ProcessPCR(const mpeg_ts_packet *pkt, bigtime_t start_time);
virtual void ProcessPAT(const mpeg_ts_packet *pkt);
virtual void ProcessAUD(const mpeg_ts_packet *pkt);
virtual void ProcessVID(const mpeg_ts_packet *pkt);
private:
int64 fCount;
bigtime_t fSystemTime;
bigtime_t fPerformanceTime;
bigtime_t fLastEndTime;
int fVidPid;
int fAudPid;
int fPcrPid;
PacketQueue * fVidQueue;
PacketQueue * fVidQueue2;
PacketQueue * fAudQueue;
PacketQueue * fAudQueue2;
PacketQueue * fMpegTsQueue;
Packet * fVidPacket;
Packet * fAudPacket;
bool fVidPacketValid;
bool fAudPacketValid;
BLocker fTimeSourceLocker;
};
inline void
TransportStreamDemux::TimesourceInfo(bigtime_t *perf_time, bigtime_t *sys_time)
{
fTimeSourceLocker.Lock();
*perf_time = fPerformanceTime;
*sys_time = fSystemTime;
fTimeSourceLocker.Unlock();
}
#endif

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _DVB_MEDIA_ADDON_CONFIG_H_
#define _DVB_MEDIA_ADDON_CONFIG_H_
#include "revision.h"
#define VERSION "1.0"
#define BUILD __DATE__ " "__TIME__
#define BUILD_FOR_HAIKU 1
#endif

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __MEDIA_HEADER_EX_H_
#define __MEDIA_HEADER_EX_H_
#include <MediaDefs.h>
struct media_audio_header_ex {
int32 _reserved_[13];
float frame_rate; // NEW!
uint32 channel_count; // NEW!
} _PACKED;
struct media_video_header_ex {
uint32 _reserved_[8];
uint32 display_line_width; // NEW!
uint32 display_line_count; // NEW!
uint32 bytes_per_row; // NEW!
uint16 pixel_width_aspect; // NEW!
uint16 pixel_height_aspect; // NEW!
float field_gamma;
uint32 field_sequence;
uint16 field_number;
uint16 pulldown_number;
uint16 first_active_line;
uint16 line_count;
} _PACKED;
struct media_header_ex {
media_type type;
media_buffer_id buffer;
int32 destination;
media_node_id time_source;
uint32 _reserved1_;
uint32 size_used;
bigtime_t start_time;
area_id owner;
type_code user_data_type;
uchar user_data[64];
uint32 _reserved2_[2];
off_t file_pos;
size_t orig_size;
uint32 data_offset;
union {
media_audio_header_ex raw_audio;
media_video_header_ex raw_video;
media_multistream_header multistream;
media_encoded_audio_header encoded_audio;
media_encoded_video_header encoded_video;
char _reserved_[64];
} u;
};
#endif

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _MPEG_TS_PACKET_H
#define _MPEG_TS_PACKET_H
#include <SupportDefs.h>
class mpeg_ts_packet
{
public:
int SyncByte() const;
int TransportError() const;
int PayloadUnitStart() const;
int PID() const;
int AdaptationFieldControl() const;
int ContinuityCounter() const;
public:
uint8 header[4];
uint8 data[184];
} _PACKED;
inline int mpeg_ts_packet::SyncByte() const
{
return header[0];
}
inline int mpeg_ts_packet::TransportError() const
{
return header[1] & 0x80;
}
inline int mpeg_ts_packet::PayloadUnitStart() const
{
return header[1] & 0x40;
}
inline int mpeg_ts_packet::PID() const
{
return ((header[1] << 8) | header[2]) & 0x1fff;
}
inline int mpeg_ts_packet::AdaptationFieldControl() const
{
return (header[3] >> 4) & 0x3;
}
inline int mpeg_ts_packet::ContinuityCounter() const
{
return header[3] & 0x0f;
}
#endif

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include "pes.h"
status_t
pes_extract(const uint8 *pes_data, size_t pes_size, const uint8 **data, size_t *size)
{
if (pes_size <= 9)
return B_ERROR;
if (pes_data[0] || pes_data[1] || pes_data[2] != 1)
return B_ERROR;
size_t header_size = 9 + pes_data[8];
if (pes_size <= header_size)
return B_ERROR;
// printf("header size %d\n", header_size);
pes_data += header_size;
pes_size -= header_size;
*data = pes_data;
*size = pes_size;
return B_OK;
}
status_t
pes_stream_id(const uint8 *pes_data, size_t pes_size, int *stream_id)
{
if (pes_size <= 9)
return B_ERROR;
if (pes_data[0] || pes_data[1] || pes_data[2] != 1)
return B_ERROR;
*stream_id = pes_data[3];
return B_OK;
}

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __PES_H
#define __PES_H
#include <SupportDefs.h>
status_t pes_extract(const uint8 *pes_data, size_t pes_size, const uint8 **data, size_t *size);
status_t pes_stream_id(const uint8 *pes_data, size_t pes_size, int *stream_id);
#endif