gpt4 book ai didi

c++ - 从 IP 摄像机流式传输在 VLC 上非常紧张

转载 作者:太空狗 更新时间:2023-10-29 23:15:42 25 4
gpt4 key购买 nike

这个问题是我之前提出的问题的序言 here .我正在从事基于 TI OMAP-L138 的 IP 摄像机项目。总而言之,H264 编码视频通过 RTSP 上的 live555 库进行流式传输。对于 Live555,我使用基于 deviceSource 的框架源。但是,当我通过 vlc 启动流时,它非常抖动并且有足够的帧丢失。deviceSource.cpp的代码如下所示:

#include "DeviceSource.hh"
#include <GroupsockHelper.hh> // for "gettimeofday()"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sstream>
#include<iostream>
#include<math.h>
//static uint8_t buf[131072];
static uint8_t buf[131072];
//uint8_t * buf = (uint8_t *)malloc(131072);
int upp_stream;
int upp_write;

DeviceSource*
DeviceSource::createNew(UsageEnvironment& env)
{

return new DeviceSource(env);
}

EventTriggerId DeviceSource::eventTriggerId = 0;

unsigned DeviceSource::referenceCount = 0;

DeviceSource::DeviceSource(UsageEnvironment& env):FramedSource(env)
{

if (referenceCount == 0)
{

upp_stream = open("/dev/upp",O_RDWR);
//upp_write = open("output_16Jan.264", O_RDWR|O_CREAT);

}
++referenceCount;

if (eventTriggerId == 0)
{
eventTriggerId = envir().taskScheduler().createEventTrigger(deliverFrame0);
}
}

DeviceSource::~DeviceSource(void) {
--referenceCount;
envir().taskScheduler().deleteEventTrigger(eventTriggerId);
eventTriggerId = 0;

if (referenceCount == 0)
{

}
}
void DeviceSource::doGetNextFrame()
{
read(upp_stream,buf, 131072);
//write(upp_write,buf, sizeof(buf));
deliverFrame();

}


void DeviceSource::deliverFrame0(void* clientData)
{
((DeviceSource*)clientData)->deliverFrame();
}

void DeviceSource::deliverFrame()
{

if (!isCurrentlyAwaitingData()) return; // we're not ready for the data yet


//Bitwise Shift hex from buf[12] to buf[15] to get data count
unsigned int data_count2 = (buf[12] << 24)|(buf[13]<<16)|(buf[14]<<8)|buf[15];

u_int8_t* newFrameDataStart = (uint8_t*)buf;
unsigned newFrameSize = sizeof(buf);//f_size;
// Deliver the data here:
if (newFrameSize > fMaxSize)
{
fFrameSize = fMaxSize;
fNumTruncatedBytes = newFrameSize - fMaxSize;
}
else
{
fFrameSize = newFrameSize;
}
gettimeofday(&fPresentationTime, NULL); //chk this
memmove(fTo, newFrameDataStart, fFrameSize);
FramedSource::afterGetting(this);



}

和测试H264VideoStreamer:

#include <liveMedia.hh>
#include <BasicUsageEnvironment.hh>
#include <GroupsockHelper.hh>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <string.h>
#include <unistd.h> //to allow read() function

UsageEnvironment* env;

H264VideoStreamFramer* videoSource;
RTPSink* videoSink;

void play(); // forward
//-------------------------------------------------------------------------
//Entry Point -> Main FUNCTION
//-------------------------------------------------------------------------

int main(int argc, char** argv) {
// Begin by setting up our usage environment:
TaskScheduler* scheduler = BasicTaskScheduler::createNew();
env = BasicUsageEnvironment::createNew(*scheduler);

// Create 'groupsocks' for RTP and RTCP:
struct in_addr destinationAddress;
destinationAddress.s_addr = chooseRandomIPv4SSMAddress(*env);
// Note: This is a multicast address. If you wish instead to stream
// using unicast, then you should use the "testOnDemandRTSPServer"
// test program - not this test program - as a model.

const unsigned short rtpPortNum = 18888;
const unsigned short rtcpPortNum = rtpPortNum+1;
const unsigned char ttl = 255;

const Port rtpPort(rtpPortNum);
const Port rtcpPort(rtcpPortNum);

Groupsock rtpGroupsock(*env, destinationAddress, rtpPort, ttl);
rtpGroupsock.multicastSendOnly(); // we're a SSM source
Groupsock rtcpGroupsock(*env, destinationAddress, rtcpPort, ttl);
rtcpGroupsock.multicastSendOnly(); // we're a SSM source

// Create a 'H264 Video RTP' sink from the RTP 'groupsock':
OutPacketBuffer::maxSize = 600000;
videoSink = H264VideoRTPSink::createNew(*env, &rtpGroupsock, 96);

// Create (and start) a 'RTCP instance' for this RTP sink:
const unsigned estimatedSessionBandwidth = 2048; // in kbps; for RTCP b/w share
const unsigned maxCNAMElen = 100;
unsigned char CNAME[maxCNAMElen+1];
gethostname((char*)CNAME, maxCNAMElen);
CNAME[maxCNAMElen] = '\0'; // just in case
RTCPInstance* rtcp
= RTCPInstance::createNew(*env, &rtcpGroupsock,
estimatedSessionBandwidth, CNAME,
videoSink, NULL /* we're a server */,
True /* we're a SSM source */);
// Note: This starts RTCP running automatically

RTSPServer* rtspServer = RTSPServer::createNew(*env, 8554);
if (rtspServer == NULL) {
*env << "Failed to create RTSP server: " << env->getResultMsg() << "\n";
exit(1);
}
ServerMediaSession* sms
= ServerMediaSession::createNew(*env, "ipcamera","Using DeviceSource" ,
"Session streamed by \"testH264VideoStreamer\"",
True /*SSM*/);
sms->addSubsession(PassiveServerMediaSubsession::createNew(*videoSink, rtcp));
rtspServer->addServerMediaSession(sms);

char* url = rtspServer->rtspURL(sms);
*env << "Play this stream using the URL \"" << url << "\"\n";
delete[] url;

// Start the streaming:
*env << "Beginning streaming...\n";
play();

env->taskScheduler().doEventLoop(); // does not return

return 0; // only to prevent compiler warning
}
//----------------------------------------------------------------------
//AFTER PLAY FUNCTION CALLED HERE
//----------------------------------------------------------------------
void afterPlaying(void* /*clientData*/)
{

play();
}
//------------------------------------------------------------------------
//PLAY FUNCTION ()
//------------------------------------------------------------------------
void play()
{


// Open the input file as with Device as the source:
DeviceSource* devSource
= DeviceSource::createNew(*env);
if (devSource == NULL)
{

*env << "Unable to read from\"" << "Buffer"
<< "\" as a byte-stream source\n";
exit(1);
}

FramedSource* videoES = devSource;

// Create a framer for the Video Elementary Stream:
videoSource = H264VideoStreamFramer::createNew(*env, videoES,False);

// Finally, start playing:
*env << "Beginning to read from UPP...\n";
videoSink->startPlaying(*videoSource, afterPlaying, videoSink);
}

uPP驱动源:

/* 
* A device driver for the Texas Instruments
* Universal Parallel Port (UPP)
*
* Modified by: Ali Shehryar <github.com/sshehryar>
*
*/

#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/fs.h>
#include <linux/delay.h> //for "mdelay(...)"
#include <linux/interrupt.h>
#include <linux/cdev.h>
#include <linux/moduleparam.h>
#include <mach/da8xx.h>
#include <asm/sizes.h>
#include <asm/io.h>
#include <mach/mux.h>
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <asm/gpio.h>

//SPRUH77A.PDF, Table 12-1. The Interrupt number assigned to the UPP module.
#define UPP_INTERRUPT 91

//SPRS586D.PDF, Table 2-4
#define DA850_UPP_BASE 0x01E16000

//SPRS586D.PDF, Table 5-117. Offsets from DA850_UPP_BASE
#define UPPCR 0x00000004
#define UPDLB 0x00000008
#define UPCTL 0x00000010
#define UPICR 0x00000014
#define UPIVR 0x00000018
#define UPTCR 0x0000001C
#define UPIER 0x00000024
#define UPIES 0x00000028
#define UPIEC 0x0000002C
#define UPEOI 0x00000030
#define UPID0 0x00000040
#define UPID1 0x00000044
#define UPID2 0x00000048
#define UPIS0 0x00000050
#define UPIS1 0x00000054
#define UPIS2 0x00000058


//SPRS586D.PDF, Table 2-4
#define DA850_PSC1_BASE 0x01E27000

//SPRUH77A.PDF, Table 9-7.
//"Power and Sleep Controller 1" (PSC1) Revision ID Register.
#define PSC_REVID 0x00000000

//SPRUH77A.PDF, Table 9-7.
//"Power Domain Transition Status" Register.
#define PSC_PTSTAT 0x00000128

//SPRUH77A.PDF, Table 9-2, Table 9-7.
//NOTE that in Table 9-2, UPP module has an LPSC number of 19...
#define PSC1_MDCTL_19 0x00000A4C //0xA00 + (19*4).

//SPRUH77A.PDF, Table 9-7.
//"Power Domain Transition Command Register" Register.
#define PSC_PTCMD 0x00000120
//DMA Status Register bitmasks used in the ISR handler....
#define EOLI 16
#define EOWI 8
#define ERRI 4
#define UORI 2
#define DPEI 1

#define UPIES_MASK 0x0000001F
//The DMA PARAMETERS
#define UPP_BUF_SIZE 131072 //Changed 6-Jan-2015
#define UPP_RX_LINE_COUNT 128 //Changed from 8 on 6-Jan-2015
#define UPP_RX_LINE_SIZE 1024
#define UPP_RX_LINE_OFFSET 1024



#define DA850_GPIO_BASE 0x01E26000



//MODIFIED BY: SHEHRYAR. Offsets from GPIO_Base (SPRS653C.PDF TABLE 5-134)

#define DIR67 0x00000088
#define OUT_DATA67 0x0000008C
#define SET_DATA67 0x00000090
#define CLR_DATA67 0x00000094

static void *rxBuf;
static void __iomem *pinmux_base = 0;
static void __iomem *upp_base = 0;
static void __iomem *psc1_base = 0;
static void __iomem *gpio_base = 0;

static DECLARE_WAIT_QUEUE_HEAD(read_queue);
static int32_t read_pending = 0; // changed from static int



static int loopbackMode = 0;

module_param( loopbackMode, int, S_IRUGO);

int EOWI_Count = 0; int UORI_count =0;



//SPRUGJ5B.PDF, Section 2.6.4
static irqreturn_t upp_ISR_handler(int irq, void *dev_id)
{
uint32_t regVal, status;

if (pinmux_base == 0)
{
return IRQ_HANDLED;
}

status = ioread32( upp_base + UPIER );


while (status & 0x0000001F ) //0x1F1F is an interrupt bit-mask
{
//
//DMA Channel I (Channel A), Receiving data (We Need A (DMA Ch I ) to Rx Data instead of Tx ; 27th Nov 2014 - 10:38am)
//
if (status & EOLI)
{
//Clear the interrupt. WRITING ZERO to any other bit has NO effect,
//per SPRUH77A.PDF, section 33.3.9.
iowrite32(EOLI, upp_base + UPIER );

//printk(KERN_INFO "DMA: EOLI\n");
//printk(KERN_INFO "DMA:EOLI. UPP_RX_LINE_SIZE[%d] UPP_RX_LINE_OFFSET[%d] UPP_RX_LINE_COUNT[%d] \n", UPP_RX_LINE_SIZE,UPP_RX_LINE_OFFSET,UPP_RX_LINE_COUNT );
//dump_Channel_regs();
}

if (status & EOWI)
{
//Clear the interrupt. WRITING ZERO to any other bit has NO effect,
//per SPRUH77A.PDF, section 33.3.9.
//printk(KERN_INFO "DMA: EOWI\n");
iowrite32(EOWI, upp_base + UPIER );

read_pending = 131072; //Changed 6-Jan-2015
wake_up_interruptible(&read_queue);
//add 1 to EOWI counter
EOWI_Count += 1;

// dump_Channel_regs();
}

if (status & ERRI)
{
//Clear the interrupt. WRITING ZERO to any other bit has NO effect,
//per SPRUH77A.PDF, section 33.3.9.
iowrite32(ERRI, upp_base + UPIER );


//dump_Channel_regs();
}
if (status & UORI)
{
//Clear the interrupt. WRITING ZERO to any other bit has NO effect,
//per SPRUH77A.PDF, section 33.3.9.
iowrite32(UORI, upp_base + UPIER );
UORI_count +=1;

//dump_Channel_regs();
}
if (status & DPEI)
{
//Clear the interrupt. WRITING ZERO to any other bit has NO effect,
//per SPRUH77A.PDF, section 33.3.9.
iowrite32(DPEI, upp_base + UPIER );


//dump_Channel_regs();
}
//read again, and process if necessary.
status = ioread32( upp_base + UPIER );
}
//Clear UPEOI to allow future calls to this function.
regVal = ioread32( upp_base + UPEOI);
regVal &= 0xFFFFFF00;
regVal = 0;// End of Interrupt

iowrite32(regVal, upp_base + UPEOI);

return IRQ_HANDLED;
}

static void pin_mux_set( int index, unsigned int bits )
{
static DEFINE_SPINLOCK(mux_spin_lock);
unsigned long flags;
unsigned int offset;

if ((index < 0) || (index > 19))
{
printk(KERN_INFO "pin_mux_set:index is out of range.\n");
return;
}

if (!pinmux_base)
{
//SRPUH77A.PDF,Table 11-3
if ((pinmux_base = ioremap(DA8XX_SYSCFG0_BASE, SZ_4K)) == 0)
{
printk(KERN_INFO "pin_mux_set:Cannot fetch pinmux_base.\n");
return;
}
}

offset = 0x120 + (index * 4);
spin_lock_irqsave(&mux_spin_lock, flags);
iowrite32(bits, pinmux_base + offset);
spin_unlock_irqrestore(&mux_spin_lock, flags);

//NOTE: do NOT "iounmap" the pinmux_base pointer, as it is used
// in the ISR_handler.....
}



static void upp_pin_mux_init(void)
{
pin_mux_set( 13, 0x44440000 );
pin_mux_set( 14, 0x44444480 );
pin_mux_set( 15, 0x44444444 );
pin_mux_set( 16, 0x44444444 );
pin_mux_set( 17, 0x44444444 );
pin_mux_set( 18, 0x00444444 );
pin_mux_set( 19, 0x08888800 );
//pin_mux_print() ;
}



static void upp_power_and_clocks( void )
{

int regVal;


if (!psc1_base)
{
if ((psc1_base = ioremap(DA850_PSC1_BASE, SZ_4K)) == 0)
{
printk(KERN_INFO "upp_power_and_clocks:Cannot fetch psc1_base.\n");
return;
}
}

regVal = ioread32(psc1_base + PSC_REVID);

//PSC Revision ID should be "44825A00" per SPRUH77A.PDF, section 9.6.1
if (regVal == 0x44825A00)
{
printk( KERN_INFO "PSC_REVID = 0x%08X....OK\n", regVal);
}
else
{
printk( KERN_INFO "********ERROR: PSC_REVID = 0x%08X********\n", regVal);
}

// SPRUH77A.PDF, 9.3.2.1, Table 9-6, 9.6.10
// wait for GOSTAT[0] in PSTAT to clear to 0 ("No transition in progress")
while ( ioread32(psc1_base + PSC_PTSTAT) & 0x00000001 )
;

//
//SPRUH77A.PDF, 9.3.2.2, 9.6.19.
//Set NEXT bit in MDCTL19 to Enable(3h).
regVal = ioread32( psc1_base + PSC1_MDCTL_19 );
regVal |= 0x00000003;
iowrite32(regVal, psc1_base + PSC1_MDCTL_19);


//
//SPRUH77A.PDF, 9.3.2.3, 9.6.9.
//Set the GO[0] bit in PTCMD to 1 to initiate power-domain transition
regVal = ioread32(psc1_base + PSC_PTCMD);
regVal |= 0x00000001;
iowrite32(regVal, psc1_base + PSC_PTCMD);

//
// SPRUH77A.PDF, 9.3.2.4
// Wait for GOSTAT[0] in PTSTAT to clear to 0
while ( ioread32(psc1_base + PSC_PTSTAT) & 0x00000001 )
;

iounmap( psc1_base );
psc1_base = 0;


}

//SPRUGJ5B.PDF, Section 2.6.1.3, 2.6.1.4
static void upp_swrst( void )
{
int32_t reg_val;

if (!upp_base)
{
if ((upp_base = ioremap(DA850_UPP_BASE, SZ_4K)) == 0)
{
printk(KERN_INFO "upp_swrst:Cannot fetch upp_base.\n");
return;
}
}

reg_val = ioread32( upp_base + 0 );
if (reg_val == 0x44231100 )
{
printk(KERN_INFO "UPP_UPPID = 0x%08X....OK\n", reg_val);
}
else
{
printk( KERN_INFO "********ERROR: UPP_UPPID = 0x%08X********\n", reg_val);
}




reg_val = ioread32( upp_base + UPPCR );
reg_val &= ~(1 << 3); //0xfffffff7;
iowrite32( reg_val, upp_base + UPPCR );

//poll "DMA Burst" (DB) bit of UPPCR to ensure DMA controller is idle
while ( ioread32( upp_base + UPPCR ) & (1 << 7) )
;


// SPRUH77A.PDF, Section 33.2.7.1.3, Table 33-12.
// assert SWRST bit (bit 4) of UPPCR
reg_val = ioread32( upp_base + UPPCR );
reg_val |= 0x00000010;
iowrite32( reg_val, upp_base + UPPCR );

//
// wait at least 200 clock cycles
// (SPRUGJ5B.PDF, 2.6.1.4)
mdelay( 200 ); // abitrary choice of 200ms


// SPRUH77A.PDF, Section 33.2.7.1.4 --AND--
// SPRUGJ5B.PDF, 2.6.1.4
// clear SWRST bit (bit 4) of UPPCR
reg_val = ioread32( upp_base + UPPCR );
reg_val &= 0xffffffef;
iowrite32( reg_val, upp_base + UPPCR );


}


//SPRUGJ5B.PDF, Section 2.6.1.5
static void upp_config( void )
{
int32_t regVal;

//-------------------------------------------------------------------------
// UPPCTL - UPP Interface Channel Settings....SPRUH77A.PDF, Section 33.3.4.
//
// - DATA and XDATA Pin assignments to Channels A & B:
// Refer to SPRUGJ5B.PDF, Table 3:
//
// ____PHYSICAL_PINS___|____CHANNEL_ASSIGNMENT___
// * DATA[7:0] | A[7:0]
// * DATA[15:8] | B[7:0]
//-------------------------------------------------------------------------
regVal = 0;
regVal |= 1 << 17; // IWA - CHANNEL A 8/16bit MODE: Set Channel A to 16 bit mode


iowrite32( regVal, upp_base + UPCTL );

regVal = 0; //Channel A: START is active-high

regVal |= 1<<3; //Channel A:STARTA is honored in Rev Mode
regVal |= 1<<4; //Channel A:ENABLEA is honored in Rev Mode
regVal |= 1<<12; //Channel A:(CLKINVA) Signal on rising edge of clock
regVal |= 1<<13; //Channel A:(TRISA) pins are High-impedence while idle

iowrite32( regVal, upp_base + UPICR );



regVal = 0;
regVal |= 0xab00; //Channel B Idle Value
regVal |= 0x00cd; //Channel A Idle Value
iowrite32( regVal, upp_base + UPIVR );



regVal = 0x00000003; //DMA Channel I READ-threshold. 256 bytes (max)

iowrite32(regVal, upp_base + UPTCR );
}

//SPRUGJ5B.PDF, Section 2.6.1.6
static void upp_interrupt_enable( void )
{
int32_t regVal, status;

// Register the ISR before enabling the interrupts....
status = request_irq( UPP_INTERRUPT, upp_ISR_handler, 0, "upp_ISR", 0 );
if( status < 0 )
{

return;
}

// clear all interrupts
iowrite32( UPIES_MASK, upp_base + UPIEC );


// regVal = 0x17; //Enable ALL interrupts (but EOWI) for DMA Channel I
//regVal |= 0x17 << 8; //Enable ALL interrupts (but EOWQ) for DMA Channel Q
regVal = UPIES_MASK;
iowrite32( regVal, upp_base + UPIES );


}


//SPRUGJ5B.PDF, Section 2.6.1.7
static void upp_enable( void )
{
int32_t reg_val;

// set EN bit in UPPCR.
// The EN bit (effectively disabling the UPP peripheral)...
// was cleared in "upp_swrst()" function
reg_val = ioread32( upp_base + UPPCR );
reg_val |= 1 << 3;
iowrite32( reg_val, upp_base + UPPCR );


}

static void upp_disable( void )
{
int32_t reg_val;

reg_val = ioread32( upp_base + UPPCR );
reg_val &= ~(1 << 3); //0xfffffff7;
iowrite32( reg_val, upp_base + UPPCR );


}


static void setpin_GPIO (void)
{

int32_t reg_val=0;

if ((gpio_base = ioremap(DA850_GPIO_BASE, SZ_4K)) == 0)
{

return;
}
//reg_val = ioread32(gpio_base + SET_DATA67);
reg_val |= (1<<6); ///Set Pin 6 of Bank 6 GP6P6 to 1 to drive GPIO high
iowrite32(reg_val,gpio_base + SET_DATA67);
}

static void clrpin_GPIO(void)
{

int32_t reg_val=0;
if ((gpio_base = ioremap(DA850_GPIO_BASE, SZ_4K)) == 0)
{
return;
}
//reg_val = ioread32(gpio_base + CLR_DATA67);
/*reg_val |= ~(1<<0);
reg_val |= ~(1<<1);
reg_val |= ~(1<<2);
reg_val |= ~(1<<3);
reg_val |= ~(1<<4);*/
reg_val |= (1<<6); //Set Pin 6 of bank 6 GP6P6 of CLR_DATA67 Register to High to drive GPIO signals low

iowrite32(reg_val,gpio_base + CLR_DATA67);

}


static void Config_GPIO(void)
{
int32_t reg_val;

if ((gpio_base = ioremap(DA850_GPIO_BASE, SZ_4K)) == 0)
{
return;
}
//set dir
reg_val = ioread32(gpio_base + DIR67);
reg_val &= ~(1<<0);
reg_val &= ~(1<<1);
reg_val &= ~(1<<2);
reg_val &= ~(1<<3);
reg_val &= ~(1<<4);
reg_val &= ~(1<<6);
iowrite32(reg_val,gpio_base + DIR67);
printk(KERN_INFO "DIR67 => [0x%08X]\n", reg_val);
//set to high
reg_val = ioread32(gpio_base + SET_DATA67);
reg_val |= (1<<0);
reg_val |= (1<<1);
reg_val |= (1<<2);
reg_val |= (1<<3);
reg_val |= (1<<4);
iowrite32(reg_val,gpio_base + SET_DATA67);

}


// Return false on error
static bool upp_mem_alloc( void )
{
//rxBuf2 = kcalloc( 1 , UPP_BUF_SIZE, GFP_KERNEL | GFP_DMA );
rxBuf = kcalloc( 1 , UPP_BUF_SIZE, GFP_KERNEL | GFP_DMA );
if (!rxBuf) //|| (!rxBuf2)
{
return false;
}

return true;
}

static void upp_program_DMA_channelA( void )
{
while ( ioread32( upp_base + UPIS2 ) & 0x00000002 );

iowrite32( rxBuf, upp_base + UPID0);
iowrite32( ( (UPP_RX_LINE_COUNT << 16) | UPP_RX_LINE_SIZE ), upp_base + UPID1);
iowrite32( UPP_RX_LINE_OFFSET, upp_base + UPID2);
}

int upp_open( struct inode *iPtr, struct file *fPtr )
{
int minor,major;
read_pending = 0;

minor=iminor(iPtr);
major=imajor(iPtr);
printk( KERN_INFO "upp_open: MAJOR(%d), MINOR(%d)\n", major, minor);

upp_disable();
upp_enable();

return 0;

}

ssize_t upp_read( struct file *fPtr, char __user *buffer, size_t size, loff_t *offset )
{

int readBytes = 0;
int retVal=0;
void *bPtr = (void *)buffer;

if (!bPtr) {return -1; printk(KERN_INFO "ERROR: bPtr not initilized\n");}

//printk(KERN_INFO "\n Begin Reading [%d] Bytes ...\n",size );

while (readBytes<size)
{
//read_flag+=1;
read_pending = 0;
//mdelay(10);

//memset(rxBuf,255,131072);


upp_program_DMA_channelA();

clrpin_GPIO();

wait_event_interruptible( read_queue, read_pending > 0 );

while ( ioread32( upp_base + UPIS2 ) & 0x00000001 )
{
printk (KERN_INFO "DMA IS STILL ACTIVE! \n");
}
setpin_GPIO(); // Set High

retVal = copy_to_user(bPtr,rxBuf,read_pending);
/* retVal = copy_to_user(bPtr,rxBuf,size);
Jan 5 2015 - Upon using size which tranfers 16k, we get copy to user failed */
if(retVal)
{
printk(KERN_INFO "ERROR: Copy to user failed!\n");
return readBytes;
}
readBytes += read_pending;

bPtr += 131072;

} //end of while loop



return readBytes;
//read_flag += 1;


}


int upp_release( struct inode *iPtr, struct file *fPtr )
{

return 0;
printk(KERN_INFO "upp_release completed.\n");
}


static struct cdev *UPP_cdev;
static dev_t UPP_MajorMinorNumbers;

struct file_operations upp_fops = {
.owner = THIS_MODULE,
//.llseek = no_llseek,
//.poll = upp_poll,
.read = upp_read,
//.write = upp_write,
//.ioctl = upp_ioctl,
.open = upp_open,
//.release = upp_release,
};


/*
* Return ZERO on success.
*
*/
static int __init upp_init(void)
{
int retVal;


if (upp_mem_alloc() == false)
{
printk(KERN_INFO "******ERROR: Could not allocate buffers. Bailing!******\n");
return -1;
}

upp_pin_mux_init();
upp_power_and_clocks();
upp_swrst();
upp_config();

upp_interrupt_enable();

upp_enable();
//SETTING GPIOS
Config_GPIO();
setpin_GPIO(); // Set High


UPP_MajorMinorNumbers = MKDEV( 0, 0);
if ( (retVal = alloc_chrdev_region( &UPP_MajorMinorNumbers, 0, 1, "UPP" )) < 0)
{
printk(KERN_INFO "ERROR: Major/Minor number allocation failed.\n");
return retVal;
}


UPP_cdev = cdev_alloc();
UPP_cdev->ops = &upp_fops;
UPP_cdev->owner = THIS_MODULE;

if (cdev_add( UPP_cdev, UPP_MajorMinorNumbers, 1) != 0)
{
printk(KERN_INFO "ERROR: UPP driver NOT loaded. CDEV registration failed.\n");
}
else
{
printk(KERN_INFO "\nUPP Major: %d , Minor: %d \n", MAJOR(UPP_MajorMinorNumbers), MINOR(UPP_MajorMinorNumbers));
}

printk("UPP driver (1.8.0 - 5/January/2015) succesfully installed.\n");

return 0;
}

/*
*
*
*
*/
static void __exit upp_exit(void)
{
uint32_t regVal;
printk(KERN_INFO "Exiting..Initializing upp_exit call......\n");

// clear EN bit of UPPCR to disable the UPP.
regVal = ioread32( upp_base + UPPCR );
regVal &= 0xfffffff7;
iowrite32( regVal, upp_base + UPPCR );


free_irq( UPP_INTERRUPT, 0);


if (rxBuf)
{
kfree( rxBuf );
rxBuf = 0;
}


cdev_del( UPP_cdev );
unregister_chrdev_region( UPP_MajorMinorNumbers, 1);
clrpin_GPIO(); //added 2-Dec-2014
printk(KERN_INFO "UPP driver unloaded (Successful Exit). \n");
}


MODULE_AUTHOR("Ali Shehryar & Umair Ali");
MODULE_DESCRIPTION("OMAP-L138/AM-1808 UPP bus driver");
MODULE_LICENSE("GPL");
module_init(upp_init)
module_exit(upp_exit)

什么可能导致我的流中出现这种抖动和丢失?我花了很多时间找出可能出了什么问题,但所有尝试都是徒劳的。我是菜鸟,非常感谢这方面的帮助。

最佳答案

因为读取是一个阻塞调用,您应该管理非阻塞读取或使用线程。但是您的内核模块似乎没有实现选择/轮询回调。

然后第一步可能是使用像这样的附加线程从 live555 主循环调用外部读取:

#include "DeviceSource.hh"
#include <GroupsockHelper.hh> // for "gettimeofday()"
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

static uint8_t buf[131072];
int upp_stream;
EventTriggerId DeviceSource::eventTriggerId = 0;
unsigned DeviceSource::referenceCount = 0;
pthread_t thid;
bool stop = false;

static void* thread(void* clientData)
{
DeviceSource* This = ((DeviceSource*)clientData);
while (!stop)
{
if (This->isCurrentlyAwaitingData())
{
::read(upp_stream, buf, sizeof(buf));
This->envir().taskScheduler().triggerEvent(DeviceSource::eventTriggerId, This);
}
}
return NULL;
}

DeviceSource* DeviceSource::createNew(UsageEnvironment& env) { return new DeviceSource(env); }
DeviceSource::DeviceSource(UsageEnvironment& env):FramedSource(env)
{
if (referenceCount == 0)
{
upp_stream = open("/dev/upp",O_RDWR);
pthread_create(&thid, NULL, thread, this);
eventTriggerId = envir().taskScheduler().createEventTrigger(deliverFrame0);
}
++referenceCount;
}

DeviceSource::~DeviceSource(void) {
--referenceCount;
if (referenceCount == 0)
{
stop=true;
pthread_join(thid, NULL);

envir().taskScheduler().deleteEventTrigger(eventTriggerId);
eventTriggerId = 0;
::close(upp_stream);
}
}

void DeviceSource::doGetNextFrame() {}

void DeviceSource::deliverFrame0(void* clientData) { ((DeviceSource*)clientData)->deliverFrame(); }
void DeviceSource::deliverFrame()
{
if (!isCurrentlyAwaitingData()) return; // we're not ready for the data yet
//Bitwise Shift hex from buf[12] to buf[15] to get data count
unsigned int data_count2 = (buf[12] << 24)|(buf[13]<<16)|(buf[14]<<8)|buf[15];

u_int8_t* newFrameDataStart = (uint8_t*)buf;
unsigned newFrameSize = sizeof(buf);//f_size;
// Deliver the data here:
if (newFrameSize > fMaxSize)
{
fFrameSize = fMaxSize;
fNumTruncatedBytes = newFrameSize - fMaxSize;
}
else
{
fFrameSize = newFrameSize;
}
gettimeofday(&fPresentationTime, NULL); //chk this
memmove(fTo, newFrameDataStart, fFrameSize);
FramedSource::afterGetting(this);
}

如您所见,这个简单示例不会在后台读取帧。这需要在两个线程之间实现一个FIFO。

更新
它可以使用 :

CPPFLAGS=-pthread LDFLAGS=-pthread make

关于c++ - 从 IP 摄像机流式传输在 VLC 上非常紧张,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28042716/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com