void dvbsub_ass_clear(void)
{
	OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(ass_mutex);

	while(ass_queue.size()) {
		ass_data *a = (ass_data *) ass_queue.pop();
		if (a) {
			avsubtitle_free(&a->sub);
			delete a;
		}
	}
	while(!sem_trywait(&ass_sem));

	ass_track = NULL;
	for(std::map<int,ASS_Track*>::iterator it = ass_map.begin(); it != ass_map.end(); ++it)
		ass_free_track(it->second);
	ass_map.clear();
	if (ass_renderer) {
		ass_renderer_done(ass_renderer);
		ass_renderer = NULL;
	}
	if (ass_library) {
		ass_library_done(ass_library);
		ass_library = NULL;
	}
	clear_queue();
}
void ReliabilitySystem::processAck( quint32 ack
									, quint32 ack_bits
									, PacketQueue & pending_ack_queue
									, PacketQueue & acked_queue
									, QVector<quint32> & acked
									, quint32 & acked_packets
									, float & rtt
									, quint32 max_sequence)
{
	if ( pending_ack_queue.empty() ){
		return;
	}

	PacketQueue::iterator itor = pending_ack_queue.begin();
	while ( itor != pending_ack_queue.end() ) {
		bool wasAcked = false;

		if ( itor->sequence == ack ) {
			wasAcked = true;
		}
		else if ( !sequenceIsMoreRecent( itor->sequence, ack, max_sequence ) ) {
			qint32 bit_index = bitIndexForSequence( itor->sequence, ack, max_sequence );
			if ( bit_index <= 31 ){
				wasAcked = ( ack_bits >> bit_index ) & 1;
			}
		}
void ReliabilitySystem::process_ack(unsigned int ack, unsigned int ack_bits,
							PacketQueue & pending_ack_queue, PacketQueue & acked_queue,
							std::vector<unsigned int> & acks, unsigned int & acked_packets,
							float & rtt, unsigned int max_sequence)
{
	if (pending_ack_queue.empty())
		return;

	PacketQueue::iterator itor = pending_ack_queue.begin();
	while (itor != pending_ack_queue.end()) {
		bool acked = false;

		if (itor->sequence == ack) {
			acked = true;
		} else if (!sequence_more_recent(itor->sequence, ack, max_sequence)) {
			int bit_index = bit_index_for_sequence(itor->sequence, ack, max_sequence);
			if (bit_index <= 31)
				acked = (ack_bits >> bit_index) & 1;
		}

		if (acked) {
			rtt += (itor->time - rtt) * 0.1f;

			acked_queue.insert_sorted(*itor, max_sequence);
			acks.push_back(itor->sequence);
			acked_packets++;
			itor = pending_ack_queue.erase(itor);
		} else {
			++itor;
		}
	}
Example #4
0
int
FIFONode::send(Packet* packet)
{
    Address 	 	nhop;
    PacketQueue* 	queue;
    QueueMapIterator	qiter;

    // Compute the nexthop
    nhop = topology->nexthop(address(), packet->destination);

    // Find the queue
    qiter = queue_map.find(nhop);
    if (qiter == queue_map.end()) { // An entry doesn't exist
        queue = new PacketQueue(max_queue_size, address(), nhop);
        QueueMapPair np(nhop, queue);
        queue_map.insert(np);
    } else {
        queue = (*qiter).second;
    }
    
    // Check if there is space
    if (queue->enq(packet)) {
        TRACE(TRL2, "Enqueued at %d packet (src %d, dst %d, id %d)\n",
              address(), packet->source, packet->destination, packet->id);
        send_it(nhop);
        return 1;
    }

    TRACE(TRL2, "Queue full at %d, dropped packet (src %d, dst %d, id %d)\n",
          address(), packet->source, packet->destination, packet->id);
    delete packet;
    return 0;
}
Example #5
0
int main(int argc, char ** argv)
{
	Connection con;	

	std::mutex zbSenderConditionVariableMutex;
	std::condition_variable zbSenderConditionVariable;
	PacketQueue zbSendQueue;
	ZBSender * zbSender = new ZBSender(con.openPort(atoi(argv[1]), 9600), &zbSenderConditionVariableMutex, &zbSenderConditionVariable, &zbSendQueue);

	
	boost::thread * zbSenderThread = new boost::thread(boost::ref(*zbSender));



	std::vector<unsigned char> zigbeeAddress64bit{0X00, 0X13, 0XA2, 0X00, 0X40, 0X69, 0X73, 0X77};
	std::vector<SensorType> sensors{TEMP, PRES, BAT};

	for(int i = 0; i < 20; ++i)
	{
		LibelAddNodePacket * libelAddNodePacket = new LibelAddNodePacket(zigbeeAddress64bit, sensors);	 	
		zbSendQueue.addPacket(dynamic_cast<Packet *> (libelAddNodePacket));
		zbSenderConditionVariableMutex.lock();
		zbSenderConditionVariable.notify_all();
		zbSenderConditionVariableMutex.unlock();
		std::cout << "packet sent" << std::endl;
		sleep(5);

	}
	zbSenderThread->join();
	delete zbSender;
	delete zbSenderThread;
	return 0;
}
		void ReliabilitySystem::process_ack( unsigned int ack, unsigned int ack_bits, 
								 PacketQueue & pending_ack_queue, PacketQueue & acked_queue, 
								 std::vector<unsigned int> & acks, unsigned int & acked_packets, 
								 float & rtt, unsigned int max_sequence )
		{
			if ( pending_ack_queue.empty() ) {
				return;
			}
				
			PacketQueue::iterator itor = pending_ack_queue.begin();
			while ( itor != pending_ack_queue.end() )
			{
				bool acked = false;
				
				if ( itor->sequence == ack )
				{
					acked = true;
				}
				else if ( !sequence_more_recent( itor->sequence, ack, max_sequence ) )
				{
					int bit_index = bit_index_for_sequence( itor->sequence, ack, max_sequence );
					if ( bit_index <= 31 ) { 
						acked = ( ack_bits >> bit_index ) & 1;
					}
				}
Example #7
0
TEST_F( PacketTest, SendPacket ) {
   const DestinationID kFirstChannel  = 5;
   const DestinationID kSecondChannel = 10;

   class TestPacketSubscriber : public PacketSubscriber {
   public:

      bool sendPacket( DestinationID destination_id )
      {
         NetAppPacket* packet_ptr = new NetAppPacket( destination_id, 100 );
         bool success = sendTo( destination_id, packet_ptr );
         if ( success == false )
         {
            delete packet_ptr;
         }
         return success;
      }

      bool put( DestinationID destination_id, const void* data_ptr, ui32 length )
      {
         return true;
      }
   };

   PacketQueue queue;
   PacketRouter router(&queue);
   TestPacketSubscriber subscriber;

   EXPECT_EQ( -1, router.count( kFirstChannel ) );
   EXPECT_EQ( -1, router.count( kSecondChannel ) );

   // Test registeration
   EXPECT_FALSE( subscriber.isSubscribed() );
   EXPECT_EQ( true, router.subscribe( kFirstChannel, &subscriber, kSubscriberModeReadWrite ) );
   EXPECT_EQ( true, router.subscribe( kSecondChannel, &subscriber, kSubscriberModeReadOnly ) );
   EXPECT_EQ( true, subscriber.isSubscribed() );
   EXPECT_EQ( 1, router.count( kFirstChannel ) );
   EXPECT_EQ( 1, router.count( kSecondChannel ) );

   // Send a packet on the first channel.
   EXPECT_EQ( true, subscriber.sendPacket( kFirstChannel ) );
   PacketContainer* container_ptr = queue.pop();
   EXPECT_TRUE( ( container_ptr != NULL ) );
   EXPECT_EQ( kFirstChannel, container_ptr->destination_id_ );
   EXPECT_EQ( 108, container_ptr->packet_ptr_->allocatedSize() );
   // delete container_ptr->packet_ptr_;
   // delete container_ptr;


   // Test unregisteration
   EXPECT_EQ( true, router.unsubscribe( kFirstChannel, &subscriber ) );
   EXPECT_EQ( true, router.unsubscribe( kSecondChannel, &subscriber ) );
   EXPECT_FALSE( subscriber.isSubscribed() );

   EXPECT_EQ( 0, router.count( kFirstChannel ) );
   EXPECT_EQ( 0, router.count( kSecondChannel ) );
}
void Inject() {
	list<InjectReqMsg> packets = packet_queue.DeQueue(cycle);
	list<InjectReqMsg>::iterator it;

	for(it = packets.begin(); it != packets.end(); ++it) {
		sendPacket(*it);
	}

	packet_queue.CleanUp(cycle);
}
unsigned int ReliabilitySystem::generate_ack_bits(unsigned int ack, const PacketQueue & received_queue, unsigned int max_sequence) {
	unsigned int ack_bits = 0;
	for (PacketQueue::const_iterator itor = received_queue.begin(); itor != received_queue.end(); itor++) {
		if (itor->sequence == ack || sequence_more_recent(itor->sequence, ack, max_sequence))
			break;
		int bit_index = bit_index_for_sequence(itor->sequence, ack, max_sequence);
		if (bit_index <= 31)
			ack_bits |= 1 << bit_index;
	}
	return ack_bits;
}
Example #10
0
casr::State::PacketQueue casr::State::get_current_packets(int process_id1, int process_id2)
{
	PacketQueue &pq = get_packets(process_id1, process_id2);
	PacketQueue result;
	for (size_t t = 0; t < pq.size(); t++) {
		if (global_time >= pq[t].start_time) {
			result.push_back(pq[t]);
		}
	}
	return result;
}
Example #11
0
static void clear_queue()
{
	uint8_t* packet;

	pthread_mutex_lock(&packetMutex);
	while(packet_queue.size()) {
		packet = packet_queue.pop();
		free(packet);
	}
	pthread_mutex_unlock(&packetMutex);
}
quint32 ReliabilitySystem::generateAckBits( quint32 ack, const PacketQueue & received_queue, quint32 max_sequence ) {
	quint32 ack_bits = 0;
	for ( PacketQueue::const_iterator itor = received_queue.begin(); itor != received_queue.end(); itor++ ) {
		if ( itor->sequence == ack || sequenceIsMoreRecent( itor->sequence, ack, max_sequence ) ){
			break;
		}
		qint32 bit_index = bitIndexForSequence( itor->sequence, ack, max_sequence );
		if ( bit_index <= 31 ){
			ack_bits |= 1 << bit_index;
		}
	}
	return ack_bits;
}
Example #13
0
TEST_F( RelayTest, CollectPacket ) {

   PacketQueue queue;
   PacketRouter router(&queue);
   TestPacketSubscriber subscriber_1;
   TestPacketSubscriber subscriber_2;
   TestPacketRelay relay;

   EXPECT_EQ( -1, router.count( kFirstChannel ) );
   EXPECT_EQ( -1, router.count( kSecondChannel ) );

   // Test registeration
   EXPECT_FALSE( subscriber_1.isSubscribed() );
   EXPECT_FALSE( subscriber_2.isSubscribed() );

   EXPECT_EQ( true, router.subscribe( RELAY_PIPE, &relay, kSubscriberModeReadWrite ) );
   EXPECT_EQ( true, relay.subscribe( kFirstChannel, &subscriber_1, kSubscriberModeReadWrite ) );
   EXPECT_EQ( true, relay.subscribe( kSecondChannel, &subscriber_2, kSubscriberModeReadWrite ) );
   EXPECT_EQ( true, subscriber_1.isSubscribed() );
   EXPECT_EQ( true, subscriber_2.isSubscribed() );
   EXPECT_EQ( 1, relay.count( kFirstChannel ) );
   EXPECT_EQ( 1, relay.count( kSecondChannel ) );

   // Route some packets.
   EXPECT_EQ( true, subscriber_1.sendPacket( kFirstChannel ) );
   EXPECT_EQ( true, subscriber_2.sendPacket( kSecondChannel ) );

   PacketContainer* container_ptr = queue.pop();
   EXPECT_TRUE( ( container_ptr != NULL ) );
   EXPECT_EQ( RELAY_PIPE, container_ptr->destination_id_ );
   NetAppPacket::Data* header_ptr = (NetAppPacket::Data*)container_ptr->packet_ptr_->basePtr();
   EXPECT_EQ( kFirstChannel, (DestinationID)header_ptr->type );

   container_ptr = queue.pop();
   EXPECT_TRUE( ( container_ptr != NULL ) );
   EXPECT_EQ( RELAY_PIPE, container_ptr->destination_id_ );
   header_ptr = (NetAppPacket::Data*)container_ptr->packet_ptr_->basePtr();
   EXPECT_EQ( kSecondChannel, (DestinationID)header_ptr->type );

   // Test unregisteration
   EXPECT_EQ( true, relay.unsubscribe( kFirstChannel, &subscriber_1 ) );
   EXPECT_EQ( true, relay.unsubscribe( kSecondChannel, &subscriber_2 ) );
   EXPECT_EQ( true, router.unsubscribe( RELAY_PIPE, &relay ) );
   EXPECT_FALSE( subscriber_1.isSubscribed() );
   EXPECT_FALSE( subscriber_2.isSubscribed() );
   EXPECT_EQ( 0, relay.count( kFirstChannel ) );
   EXPECT_EQ( 0, relay.count( kSecondChannel ) );
   EXPECT_EQ( 0, router.count( RELAY_PIPE ) );
}
Example #14
0
// pushQueue
void PacketQueueThread::pushQueue(PacketQueue &packetQueue, int maxQueueLen) {
    // 是停止就不允许放了
    if (_stop) {
        return;
    }

    // 是否要限制push长度
    if (maxQueueLen>0 && _queue._size >= maxQueueLen) {
        _pushcond.lock();
        _waiting = true;
        while (_stop == false && _queue.size() >= maxQueueLen) {
            _pushcond.wait(1000);
        }
        _waiting = false;
        _pushcond.unlock();
        if (_stop) {
            return;
        }
    }

    // 加锁写入队列
    _cond.lock();
    packetQueue.moveTo(&_queue);
    _cond.unlock();
    _cond.signal();
}
static void clear_queue()
{
	uint8_t* packet;
	cDvbSubtitleBitmaps *Bitmaps;

	pthread_mutex_lock(&packetMutex);
	while(packet_queue.size()) {
		packet = packet_queue.pop();
		free(packet);
	}
	while(bitmap_queue.size()) {
		Bitmaps = (cDvbSubtitleBitmaps *) bitmap_queue.pop();
		delete Bitmaps;
	}
	pthread_mutex_unlock(&packetMutex);
}
void dvbsub_ass_write(AVCodecContext *c, AVSubtitle *sub, int pid)
{
	if (ass_reader_running) {
		ass_queue.push((uint8_t *)new ass_data(c, sub, pid));
		sem_post(&ass_sem);
		memset(sub, 0, sizeof(AVSubtitle));
	} else
		avsubtitle_free(sub);
}
void dvbsub_write(AVSubtitle *sub, int64_t pts)
{
	pthread_mutex_lock(&packetMutex);
	cDvbSubtitleBitmaps *Bitmaps = new cDvbSubtitleBitmaps(pts);
	Bitmaps->SetSub(sub); // Note: this will copy sub, including all references. DON'T call avsubtitle_free() from the caller.
	memset(sub, 0, sizeof(AVSubtitle));
	bitmap_queue.push((unsigned char *) Bitmaps);
	pthread_cond_broadcast(&packetCond);
	pthread_mutex_unlock(&packetMutex);
}
Example #18
0
void
FIFONode::receive(Packet* pkt)
{
    PacketQueue*	queue;
    QueueMapIterator	qiter;
    Address		nhop;

    // If the packet is for us, drop it
    if (pkt->destination == address()) {
        delete pkt;
        return;
    }

    // Otherwise, forward packet onwards
    nhop = topology->nexthop(address(), pkt->destination);

    // Find the queue
    qiter = queue_map.find(nhop);
    if (qiter == queue_map.end()) { // An entry doesn't exist
        queue = new PacketQueue(max_queue_size, address(), nhop);
        QueueMapPair np(nhop, queue);
        queue_map.insert(np);
    } else {
        queue = (*qiter).second;
    }
    
    // Check if there is space
    if (queue->enq(pkt)) {
        TRACE(TRL2, "Forwarding at %d nexthop %d packet (src %d, dst %d, id %d)\n",
              address(), nhop, pkt->source, pkt->destination, pkt->id);
        send_it(nhop);
        return;
    }

    TRACE(TRL2, "Queue full at %d, dropped packet (src %d, dst %d, id %d)\n",
          address(), pkt->source, pkt->destination,
          pkt->id);
    delete pkt;
    return;
}
Example #19
0
static int ReadRTPFunc(void *opaque, uint8_t *buf, int buf_size) {
    //printf("WIN 2!!!!!! %d\n", buf_size);
    FLOWPacket pkt;
    int written_size = 0;
    PacketQueue* q = (PacketQueue*)opaque;
    int ret = q->get(&pkt);
    int i = 0;
    //printf("Queue Size %d %d\n", q->m_PlayoutPackets->size(), pkt.m_SeqNum);
    if ( (ret != 1) && (written_size + pkt.m_Size < 1473)) {
        i++;
        memcpy(buf+written_size, pkt.m_Data, pkt.m_Size);
        written_size += pkt.m_Size;
        //delete pkt.m_Data;
        //ret = q->get(&pkt);
    }
    
    //printf("Written !!!!!! %d %d %d\n", written_size, buf_size, ret);
    if ( written_size == 0 ) {
        inputExhausted = true;
    }
    return written_size;
}
void QueuePacket(int source, int destination, int msgType, int coType,
		int packetSize, int time, int address) {
	InjectReqMsg packet;
	packet.source = source;
	packet.dest = destination;
	packet.cl = 0;
	packet.network = 0;
	packet.packetSize = packetSize;
	packet.msgType = msgType;
	packet.coType = coType;
	packet.address = address;

	packet_queue.Enqueue(packet, time);
}
Example #21
0
void
FIFONode::send_it(Address nhop)
{
    PacketQueue*	queue;
    QueueMapIterator	qiter;
    Packet*		pkt;

    qiter = queue_map.find(nhop);
    ASSERT(qiter != queue_map.end());
    queue = (*qiter).second;

    if (queue->pending_send) {
        return;
    }

    pkt = queue->deq();
    if (pkt) {
        TRACE(TRL2, "Forwarding at %d to nexthop %d packet (src %d, dst %d, id %d)\n",
              address(), nhop, pkt->source, pkt->destination, pkt->id);
        Node::send(pkt, nhop);
        queue->pending_send = 1;
    }
    return;
}
Example #22
0
void test_packet_queue()
{
	printf( "-----------------------------------------------------\n" );
	printf( "test packet queue\n" );
	printf( "-----------------------------------------------------\n" );

	const unsigned int MaximumSequence = 255;

	PacketQueue packetQueue;

	printf( "check insert back\n" );
	for ( int i = 0; i < 100; ++i )
	{
		PacketData data;
		data.sequence = i;
		packetQueue.insert_sorted( data, MaximumSequence );
		packetQueue.verify_sorted( MaximumSequence );
	}

	printf( "check insert front\n" );
	packetQueue.clear();
	for ( int i = 100; i < 0; ++i )
	{
		PacketData data;
		data.sequence = i;
		packetQueue.insert_sorted( data, MaximumSequence );
		packetQueue.verify_sorted( MaximumSequence );
	}

	printf( "check insert random\n" );
	packetQueue.clear();
	for ( int i = 100; i < 0; ++i )
	{
		PacketData data;
		data.sequence = rand() & 0xFF;
		packetQueue.insert_sorted( data, MaximumSequence );
		packetQueue.verify_sorted( MaximumSequence );
	}

	printf( "check insert wrap around\n" );
	packetQueue.clear();
	for ( int i = 200; i <= 255; ++i )
	{
		PacketData data;
		data.sequence = i;
		packetQueue.insert_sorted( data, MaximumSequence );
		packetQueue.verify_sorted( MaximumSequence );
	}
	for ( int i = 0; i <= 50; ++i )
	{
		PacketData data;
		data.sequence = i;
		packetQueue.insert_sorted( data, MaximumSequence );
		packetQueue.verify_sorted( MaximumSequence );
	}
}
static void *ass_reader_thread(void *)
{
	set_threadname("ass_reader_thread");
	while (!sem_wait(&ass_sem)) {
		if (!ass_reader_running)
			break;

		ass_data *a = (ass_data *) ass_queue.pop();
		if (!a) {
			if (!ass_reader_running)
				break;
			continue;
		}

		OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(ass_mutex);
		std::map<int,ASS_Track*>::iterator it = ass_map.find(a->pid);
		ASS_Track *track;
		if (it == ass_map.end()) {
			CFrameBuffer *fb = CFrameBuffer::getInstance();
			int xres = fb->getScreenWidth(true);
			int yres = fb->getScreenHeight(true);
			if (!ass_library) {
				ass_library = ass_library_init();
				ass_set_extract_fonts(ass_library, 1);
				ass_set_style_overrides(ass_library, NULL);
				ass_renderer = ass_renderer_init(ass_library);
				ass_set_frame_size(ass_renderer, xres, yres);
				ass_set_margins(ass_renderer, 3 * yres / 100, 3 * yres / 100, 3 * xres / 100, 3 * xres / 100);
				ass_set_use_margins(ass_renderer, 1);
				ass_set_hinting(ass_renderer, ASS_HINTING_LIGHT);
				ass_set_aspect_ratio(ass_renderer, 1.0, 1.0);
				ass_font = *sub_font_file;
				ass_set_fonts(ass_renderer, ass_font.c_str(), "Arial", 0, NULL, 1);
			}
			track = ass_new_track(ass_library);
			track->PlayResX = xres;
			track->PlayResY = yres;
			ass_size = sub_font_size;
			ass_set_font_scale(ass_renderer, ((double) ass_size)/ASS_CUSTOM_FONT_SIZE);
			if (a->c->subtitle_header) {
				std::string ass_hdr = ass_subtitle_header_default();
				if (ass_hdr.compare((char*) a->c->subtitle_header)) {
					ass_process_codec_private(track, (char *) a->c->subtitle_header, a->c->subtitle_header_size);
				} else {
					// This is the FFMPEG default ASS header. Use something more suitable instead:
					ass_hdr = ass_subtitle_header_custom();
					ass_process_codec_private(track, (char *) ass_hdr.c_str(), ass_hdr.length());
				}
			}
			ass_map[a->pid] = track;
			if (a->pid == dvbsub_pid)
				ass_track = track;
//fprintf(stderr, "### got subtitle track %d, subtitle header: \n---\n%s\n---\n", pid, c->subtitle_header);
		} else
			track = it->second;
		for (unsigned int i = 0; i < a->sub.num_rects; i++)
			if (a->sub.rects[i]->ass)
				ass_process_data(track, a->sub.rects[i]->ass, strlen(a->sub.rects[i]->ass));
		avsubtitle_free(&a->sub);
		delete a;
	}
	ass_reader_running = false;
	pthread_exit(NULL);
}
uint8_t oplug_mp4(const char *name, ADM_OUT_FORMAT type)
{
AVDMGenericVideoStream *_incoming=NULL;
AVDMGenericAudioStream  *audio=NULL;

uint8_t		audioBuffer[48000];
uint8_t         *videoBuffer=NULL;

uint32_t alen;//,flags;
uint32_t size;

uint8_t   ret=0;

uint32_t  sample_got=0,sample;
uint32_t  extraDataSize=0;
uint8_t   *extraData=NULL;
lavMuxer  *muxer=NULL;
aviInfo      info;
uint32_t   width,height;
DIA_encoding *encoding_gui=NULL;
Encoder         *_encode=NULL;
char            *TwoPassLogFile=NULL;
uint32_t total=0;
uint32_t videoExtraDataSize=0;
uint8_t  *videoExtraData=NULL;
uint8_t *dummy,err;
WAVHeader *audioinfo=NULL;
int prefill=0;
uint32_t displayFrame=0;
ADMBitstream    bitstream(0);
uint32_t        frameWrite=0;
ADM_MUXER_TYPE muxerType=MUXER_MP4;
uint8_t dualPass=0;
uint8_t r=0;
uint32_t skipping=1;
pthread_t     audioThread;
audioQueueMT context;
PacketQueue   *pq;//("MP4 audioQ",50,2*1024*1024);
uint32_t    totalAudioSize=0;
uint32_t sent=0;
const char *containerTitle;
           switch(type)
           {
             case ADM_PSP:muxerType=MUXER_PSP;containerTitle="PSP";break;
             case ADM_MP4:muxerType=MUXER_MP4;containerTitle="MP4";break;
             case ADM_MATROSKA:muxerType=MUXER_MATROSKA;containerTitle="MKV";break;
             default:
                ADM_assert(0);
           }
        // Setup video
        
        if(videoProcessMode())
        {
             _incoming = getLastVideoFilter (frameStart,frameEnd-frameStart);
        }else
        {
             _incoming = getFirstVideoFilter (frameStart,frameEnd-frameStart);
        }

           videoBuffer=new uint8_t[_incoming->getInfo()->width*_incoming->getInfo()->height*3];
                // Set global header encoding, needed for H264
           _encode = getVideoEncoder (_incoming->getInfo()->width,
                        _incoming->getInfo()->height,1);
           total= _incoming->getInfo()->nb_frames;

           encoding_gui=new DIA_encoding(_incoming->getInfo()->fps1000);
           bitstream.bufferSize=_incoming->getInfo()->width*_incoming->getInfo()->height*3;
           if (!_encode)
                {
                  GUI_Error_HIG (QT_TR_NOOP("Cannot initialize the video stream"), NULL);
                        goto  stopit;
                }

                // init compressor
               
                  encoding_gui->setContainer(containerTitle);
               
                encoding_gui->setAudioCodec("None");
                if(!videoProcessMode())
                        encoding_gui->setCodec("Copy");
                else
                        encoding_gui->setCodec(_encode->getDisplayName());
                TwoPassLogFile=new char[strlen(name)+6];
                strcpy(TwoPassLogFile,name);
                strcat(TwoPassLogFile,".stat");
                _encode->setLogFile(TwoPassLogFile,total);

                if (!_encode->configure (_incoming))
                {
                      GUI_Error_HIG (QT_TR_NOOP("Filter init failed"), NULL);
                     goto  stopit;
                };

                dualPass=_encode->isDualPass();
                if(dualPass)
                {
                       
                        if(!prepareDualPass(bitstream.bufferSize,videoBuffer,TwoPassLogFile,encoding_gui,_encode,total))
                                goto stopit;
                }else
                {
                        encoding_gui->setPhasis ("Encoding");
                }
                
                info.width=_incoming->getInfo()->width;
                info.height=_incoming->getInfo()->height;
                info.nb_frames=_incoming->getInfo()->nb_frames;
                info.fps1000=_incoming->getInfo()->fps1000;
                info.fcc=*(uint32_t *)_encode->getCodecName(); //FIXME
                _encode->hasExtraHeaderData( &videoExtraDataSize,&dummy);
                if(videoExtraDataSize)
                {
                        printf("We have extradata for video in copy mode (%d)\n",videoExtraDataSize);
                        videoExtraData=new uint8_t[videoExtraDataSize];
                        memcpy(videoExtraData,dummy,videoExtraDataSize);
                }
        // _________________Setup video (cont) _______________
        // ___________ Read 1st frame _________________
             
             ADM_assert(_encode);
             bitstream.data=videoBuffer;
             
preFilling:
             bitstream.cleanup(0);
             if(!(err=_encode->encode ( prefill, &bitstream)))//&len, videoBuffer, &flags,&displayFrame))
             {
                        printf("MP4:First frame error\n");
                        GUI_Error_HIG (QT_TR_NOOP("Error while encoding"), NULL);
                        goto  stopit;
              }
              sent++;
              if(!bitstream.len)
              {
                prefill++;
                goto preFilling;
              }
              printf("Pass 2 prefill : %u\n",prefill);
              if(!bitstream.flags & AVI_KEY_FRAME)
              {
                GUI_Error_HIG (QT_TR_NOOP("KeyFrame error"),QT_TR_NOOP( "The beginning frame is not a key frame.\nPlease move the A marker."));
                  goto  stopit; 
              }
           //len=bitstream.len;
           // If needed get VOL header
           if(isMpeg4Compatible(info.fcc) && !videoExtraDataSize && bitstream.len)
           {
                // And put them as extradata for esds atom
                uint32_t voslen=0;
               
                if(extractVolHeader(videoBuffer,bitstream.len,&voslen))
                {
                        if(voslen)
                        {
                                videoExtraDataSize=voslen;
                                videoExtraData=new uint8_t[videoExtraDataSize];
                                memcpy(videoExtraData,videoBuffer,videoExtraDataSize);
                        }
                } else  printf("Oops should be settings data for esds\n");
            }

// ____________Setup audio__________________
          if(currentaudiostream)
          {
                audio=mpt_getAudioStream();
                if(!audio)
                {
                        GUI_Error_HIG (QT_TR_NOOP("Cannot initialize the audio stream"), NULL);
                        goto  stopit;
                }
          } 
          if(audio)
          {
                audioinfo=audio->getInfo();
                audio->extraData(&extraDataSize,&extraData);
                if(audioProcessMode())
                        encoding_gui->setAudioCodec(getStrFromAudioCodec(audio->getInfo()->encoding));
                else
                         encoding_gui->setAudioCodec("Copy");

           }else
           {
                encoding_gui->setAudioCodec("None");
           }
// ____________Setup Muxer _____________________
           muxer= new lavMuxer;
           
           if(!muxer->open(
                name,
                2000000, // Muxrate
                muxerType,
                &info,videoExtraDataSize,videoExtraData,
                audioinfo,extraDataSize,extraData))
                         goto stopit;
//_____________ Loop _____________________
          
          encoding_gui->setContainer(containerTitle);
         
          if(!videoProcessMode())
                encoding_gui->setCodec("Copy");
          else
                encoding_gui->setCodec(_encode->getDisplayName());
           //
          UI_purge();
          if(bitstream.len)
          {
            muxer->writeVideoPacket( &bitstream);
            frameWrite++;
          }
//_____________ Start Audio thread _____________________
          if(audio)
          {          
            pq=new PacketQueue("MP4 audioQ",5000,2*1024*1024);
            memset(&context,0,sizeof(context));
            context.audioEncoder=audio;
            context.audioTargetSample=0xFFFF0000; ; //FIXME
            context.packetQueue=pq;
            // start audio thread
            ADM_assert(!pthread_create(&audioThread,NULL,(THRINP)defaultAudioQueueSlave,&context)); 
            ADM_usleep(4000);
          }
//_____________GO !___________________
           for(int frame=1;frame<total;frame++)
           {
               while(muxer->needAudio())
               {
                    if(pq->Pop(audioBuffer,&alen,&sample))
                    {
                     if(alen)
                     {
                        muxer->writeAudioPacket(alen,audioBuffer,sample_got);
                        totalAudioSize+=alen;
                        encoding_gui->setAudioSize(totalAudioSize);
                        sample_got+=sample;
                     }
                    }else break;
               }
               ADM_assert(_encode);
               bitstream.cleanup(frameWrite);
               if(!prefill || frame+prefill<total) 
               {
                  
                  r=_encode->encode ( prefill+frame, &bitstream);
               }
                else
                {
                    r=_encode->encode ( total-1, &bitstream);
                }
               if(!r && frame<total-2)
               {
                        printf("MP4:Frame %u error\n",frame);
                        GUI_Error_HIG (QT_TR_NOOP("Error while encoding"), NULL);
                        goto  stopit;
                }
                if(!bitstream.len && skipping)
                {
                    printf("Frame skipped (xvid ?)\n");
                    continue;
                }
                sent++;
                skipping=0;
            //    printf("Prefill %u FrameWrite :%u Frame %u PtsFrame :%u\n",prefill,frameWrite,frame,bitstream.ptsFrame);
                frameWrite++;
                muxer->writeVideoPacket( &bitstream);
                encoding_gui->setFrame(frame,bitstream.len,bitstream.out_quantizer,total);
               if(!encoding_gui->isAlive())
                {
                    
                    goto stopit;
                }
               
           }
           ret=1;
           
stopit:
    printf("2nd pass, sent %u frames\n",sent);
    // Flush slave Q
    if(audio)
    {
        context.audioAbort=1;
        pq->Abort();
        // Wait for audio slave to be over
        while(!context.audioDone)
        {
          printf("Waiting Audio thread\n");
          ADM_usleep(500000); 
        }
        delete pq;
    }
    //
           if(muxer) muxer->close();
           if(encoding_gui) delete encoding_gui;
           if(TwoPassLogFile) delete [] TwoPassLogFile;
           if(videoBuffer) delete [] videoBuffer;
           if(muxer) delete muxer;
           if(_encode) delete _encode;	
           if(videoExtraData) delete [] videoExtraData;
           // Cleanup
           deleteAudioFilter (audio);
           return ret;
}
uint8_t mpeg_passthrough(const char *name,ADM_OUT_FORMAT format )
{
  uint32_t len, flags;
  AVDMGenericAudioStream *audio=NULL;
  uint32_t audiolen;
  
  DIA_encoding *work;
  ADM_MUXER_TYPE mux;
  
  double total_wanted=0;
  uint32_t total_got=0;
  uint8_t ret=0;
 
  ADMMpegMuxer *muxer=NULL;
  ADMBitstream bitstream(0);
  
  	printf("Saving as mpg PS to file %s\n",name);
  
  	// First we check it is mpeg
	if(!isMpeg12Compatible(avifileinfo->fcc))
  	{
          GUI_Error_HIG(QT_TR_NOOP("This is not MPEG compatible"), QT_TR_NOOP("You can't use the Copy codec."));
		return 0 ;
  	}
  	if(!currentaudiostream)
  	{
          GUI_Error_HIG(QT_TR_NOOP("There is no audio track"), NULL);
		return 0;
  	}
  
	ADM_assert (video_body->getFlags (frameStart, &flags));
        if(!(flags&AVI_KEY_FRAME))
        {
          GUI_Error_HIG(QT_TR_NOOP("The first frame is not intra frame"), QT_TR_NOOP("Use the &lt;&lt; and the &gt;&gt; buttons to move using Intra frames."));
                return 0;
        }
	
  	audio=mpt_getAudioStream();
	
	// Have to check the type
	// If it is mpeg2 we use DVD-PS
	// If it is mpeg1 we use VCD-PS
	// Later check if it is SVCD
	if(!audio)
	{
          GUI_Error_HIG(QT_TR_NOOP("Audio track is not suitable"), NULL);
		return 0;
	}
	// Check
	WAVHeader *hdr=audio->getInfo();
	uint32_t isMpeg1;
	uint32_t isLav;
	if(!prefs->get(FEATURE_USE_LAVCODEC_MPEG2, &isLav))
		{
		 isLav=0;
		}

	if(!isLav)
	{
		decoderMpeg *mpeghdr;
	
		mpeghdr=(decoderMpeg *)video_body->rawGetDecoder(0);
		isMpeg1=mpeghdr->isMpeg1();
	}
	else
	{
		// How to know if it is mpeg 1?
		// Assume it is not
		/*
		decoderFFMpeg12 *mpeghdr;
	
		mpeghdr=(decoderFFMpeg12 *)video_body->rawGetDecoder(0);
		isMpeg1=mpeghdr->isMpeg1();
		*/
		isMpeg1=0;
	
	}
	
	switch(format)
        {
        case ADM_PS:	
                if(isMpeg1)
                {
                        if(hdr->frequency!=44100 ||  hdr->encoding != WAV_MP2)
                        {
                          GUI_Error_HIG(QT_TR_NOOP("Incompatible audio"), QT_TR_NOOP("For VCD, audio must be 44.1 kHz MP2."));
                                return 0 ;
                        }
                        mux=MUXER_VCD;
                        printf("PassThrough: Using VCD PS\n");        
                }else
                {    // Mpeg2 
                        aviInfo info;
                        video_body->getVideoInfo(&info);
                        if(hdr->frequency==44100 && info.width==480&& hdr->encoding == WAV_MP2 ) // SVCD ?
                        {
                                mux=MUXER_SVCD;
                                printf("PassThrough: Using SVCD PS\n");
                        }
                        else
                        {
                            uint32_t valid=0;
                                if(!prefs->get(FEATURE_MPEG_NO_LIMIT,&valid)) valid=0;
                                 // mpeg2, we do only DVD right now
                                if(hdr->frequency==48000) valid=1;
                                if((hdr->encoding != WAV_MP2 && hdr->encoding!=WAV_AC3 && hdr->encoding!=WAV_LPCM
                                && hdr->encoding!=WAV_DTS))
                                {
                                  valid=0;  
                                }
                    
                                if(!valid)
                                {
                                        deleteAudioFilter(audio);
                                       GUI_Error_HIG(("Incompatible audio"),QT_TR_NOOP( "For DVD, audio must be 48 kHz MP2(stereo), AC3, DTS or LPCM (stereo)."));
                                       return 0;
                                }
                         
                               mux=MUXER_DVD;
                               printf("PassThrough: Using DVD PS\n");
                        }
                }

  	        muxer=new mplexMuxer();
                break;
        case ADM_TS:     
             printf("Using TS output format\n");   
             muxer=new tsMuxer(); //lavMuxer();
             mux=MUXER_TS;
             break;
        default:
                ADM_assert(0);
                break;
        }
        
        if(!muxer)
         {
                 printf("No muxer ?\n");
                 return 0;
        }
	if(!muxer->open(name,0,mux,avifileinfo,audio->getInfo()))
	{
		delete muxer;
		muxer=NULL;
		printf("Muxer init failed\n");
		return 0;
		
	}
        
	// In copy mode it is better to recompute the gop timestamp
	muxer->forceRestamp();
  ///____________________________
  work=new DIA_encoding(avifileinfo->fps1000);
  work->setCodec(QT_TR_NOOP("Copy"));
  work->setAudioCodec(QT_TR_NOOP("---"));
  work->setPhasis(QT_TR_NOOP("Saving"));
  if(!audioProcessMode())
     work->setAudioCodec(QT_TR_NOOP("Copy"));
  else
     work->setAudioCodec(getStrFromAudioCodec(audio->getInfo()->encoding));
  switch(mux)
  {
    case MUXER_TS: work->setContainer(QT_TR_NOOP("MPEG TS"));break;
    case MUXER_VCD: work->setContainer(QT_TR_NOOP("MPEG VCD"));break;
    case MUXER_SVCD: work->setContainer(QT_TR_NOOP("MPEG SVCD"));break;
    case MUXER_DVD: work->setContainer(QT_TR_NOOP("MPEG DVD"));break;
    default:
        ADM_assert(0);
  }
  
  uint32_t cur=0;
  uint32_t target_sample=0;
  double target_time;
  aviInfo info;
        video_body->getVideoInfo(&info);
        target_time=frameEnd-frameStart+1;
        target_time*=1000;
        target_time/=info.fps1000; // target_time in second
        target_time*=audio->getInfo()->frequency;
        target_sample=(uint32_t)floor(target_time);

  uint8_t *buffer = new uint8_t[avifileinfo->width * avifileinfo->height * 3];
  uint8_t *audiobuffer = new uint8_t[4*48000*2]; // 2 sec worth of lpcm
  uint32_t position;
  EncoderCopy *copy=NULL;
        bitstream.data=buffer;
        bitstream.bufferSize=avifileinfo->width * avifileinfo->height * 3;
        
     /***************************
      Special case : Multithreaded
     ***************************/
        if(mux==MUXER_VCD || mux==MUXER_SVCD || mux==MUXER_DVD)
        {
          pthread_t audioThread,videoThread,muxerThread;
          copy=new EncoderCopy(NULL);
          muxerMT context;
          
          copy->configure(NULL);
          // 
          memset(&context,0,sizeof(context));
          context.videoEncoder=copy;
          context.audioEncoder=audio;
          context.muxer=( mplexMuxer *)muxer;
          context.nbVideoFrame=copy->getNbFrame();
          context.audioTargetSample=target_sample;
          context.audioBuffer=audiobuffer;
          context.bitstream=&bitstream;
          context.opaque=(void *)work;

           // start audio thread
          ADM_assert(!pthread_create(&audioThread,NULL,(THRINP)defaultAudioSlave,&context)); 
          ADM_assert(!pthread_create(&videoThread,NULL,(THRINP)copyVideoSlave,&context)); 
          while(1)
          {
            accessMutex.lock();
            if(context.audioDone==2 || context.videoDone==2 || !work->isAlive()) //ERROR
            {
              context.audioAbort=1;
              context.videoAbort=1;
              printf("[Copy] aborting\n");
            }
            if(context.audioDone && context.videoDone)
            {
              printf("[Copy]Both audio & video done\n");
              if(context.audioDone==1 && context.videoDone==1) ret=1;
              else ret=0;
              accessMutex.unlock();
              goto _abt;
            }
             // Update UI
            work->setAudioSize(context.feedAudio);
            context.feedVideo=0;
            accessMutex.unlock();
            ADM_usleep(1000*1000);
             
          }    
    
    
        }
        /**************************************************************************************/
        /* If we get here, it means output is MPEG_TS */ 
        /* We must use the audio packet Queue */
        /**************************************************************************************/
        ADM_assert(mux==MUXER_TS);
        {
            PacketQueue *pq;
            uint32_t mx,sample;
            pthread_t     audioThread;
            copy=new EncoderCopy(NULL);
            audioQueueMT context;
            uint8_t r;
            
            copy->configure(NULL);
            pq=new PacketQueue("TS audioQ",5000,2*1024*1024);
            memset(&context,0,sizeof(context));
            context.audioEncoder=audio;
            context.audioTargetSample=target_sample;
            context.packetQueue=pq;
              // start audio thread
            ADM_assert(!pthread_create(&audioThread,NULL,(THRINP)defaultAudioQueueSlave,&context));
            // Go!
             
            ADM_usleep(4000);
            mx=copy->getNbFrame();
            printf("Writing %u frames\n",mx);
            for(int frame=0;frame<mx;frame++)
            {
              while(muxer->needAudio())
              {
                if(pq->Pop(audiobuffer,&audiolen,&sample))
                {
                  if(audiolen)
                  {
                    muxer->writeAudioPacket(audiolen,audiobuffer);
                    //work->feedAudioFrame(audiolen);
                  }
                }else break;
              }
              ADM_assert(copy);
              bitstream.cleanup(frame);
              r=copy->encode ( frame, &bitstream);
              if(!r)
              {
                printf("TS:Frame %u error\n",frame);
                GUI_Error_HIG (QT_TR_NOOP("Error while encoding"), NULL);
                goto  stopit;
              }
              muxer->writeVideoPacket( &bitstream);

              work->setFrame(frame,bitstream.len,bitstream.out_quantizer,mx);
//              work->feedFrame(bitstream.len);
              if(!work->isAlive())
              {
                goto stopit;
              }
            }
        
    ret=1;
stopit:
    context.audioAbort=1;
    pq->Abort();
    // Wait for audio slave to be over
    while(!context.audioDone)
    {
      printf("Waiting Audio thread\n");
      ADM_usleep(500000); 
    }
    delete pq;
  } // End ts case 
  /************************************** TS End *********************************/
_abt:
  delete work;
  muxer->close();
  delete muxer;
  delete [] buffer;
  delete [] audiobuffer;
  deleteAudioFilter(audio);
  if(copy) delete copy;
  return ret;

}
Example #26
0
static void* reader_thread(void * /*arg*/)
{
	uint8_t tmp[16];  /* actually 6 should be enough */
	int count;
	int len;
	uint16_t packlen;
	uint8_t* buf;

        dmx = new cDemux();

#if defined (PLATFORM_COOLSTREAM)
	dmx->Open(DMX_PES_CHANNEL);
#else	
	dmx->Open(DMX_PES_CHANNEL, 64*1024, live_fe);
#endif	

	while (reader_running) 
	{
		//dmx->Open(DMX_PES_CHANNEL, 64*1024, live_fe?live_fe->fenumber:0);	
		
		if(dvbsub_stopped /*dvbsub_paused*/) 
		{
			sub_debug.print(Debug::VERBOSE, "%s stopped\n", __FUNCTION__);
			dmx->Stop();

			pthread_mutex_lock(&packetMutex);
			pthread_cond_broadcast(&packetCond);
			pthread_mutex_unlock(&packetMutex);

			pthread_mutex_lock(&readerMutex );
			int ret = pthread_cond_wait(&readerCond, &readerMutex);
			pthread_mutex_unlock(&readerMutex);

			if (ret) 
			{
				sub_debug.print(Debug::VERBOSE, "pthread_cond_timedwait fails with %d\n", ret);
			}
			if(!reader_running)
				break;
			dvbsub_stopped = 0;
			sub_debug.print(Debug::VERBOSE, "%s (re)started with pid 0x%x\n", __FUNCTION__, dvbsub_pid);
		}

		if(pid_change_req) 
		{
			pid_change_req = 0;
			clear_queue();
			dmx->Stop();
			//
#if defined (PLATFORM_COOLSTREAM)
			dmx->Open(DMX_PES_CHANNEL);
#else			
			dmx->Open(DMX_PES_CHANNEL, 64*1024, live_fe/*?live_fe->fenumber:0*/);	
#endif			
			//
			dmx->pesFilter(dvbsub_pid);
			dmx->Start();
			sub_debug.print(Debug::VERBOSE, "%s changed to pid 0x%x\n", __FUNCTION__, dvbsub_pid);
		}

		len = 0;
		count = 0;

		len = dmx->Read(tmp, 6, 1000);
		
		//printf("\n[dvbsub] len: %d\n", len);
		
		if(len <= 0)
			continue;

		if(memcmp(tmp, "\x00\x00\x01\xbd", 4)) 
		{
			sub_debug.print(Debug::VERBOSE, "[subtitles] bad start code: %02x%02x%02x%02x\n", tmp[0], tmp[1], tmp[2], tmp[3]);
			continue;
		}
		count = 6;

		packlen =  getbits(tmp, 4*8, 16) + 6;

		buf = (uint8_t*) malloc(packlen);

		memcpy(buf, tmp, 6);
		
		/* read rest of the packet */
		while((count < packlen) /* && !dvbsub_paused*/) 
		{
			len = dmx->Read(buf+count, packlen-count, 1000);
			if (len < 0) {
				continue;
			} else {
				count += len;
			}
		}
#if 0
		for(int i = 6; i < packlen - 4; i++) {
			if(!memcmp(&buf[i], "\x00\x00\x01\xbd", 4)) {
				int plen =  getbits(&buf[i], 4*8, 16) + 6;
				printf("[subtitles] PES header at %d ?!\n", i);
				printf("[subtitles] start code: %02x%02x%02x%02x len %d\n", buf[i+0], buf[i+1], buf[i+2], buf[i+3], plen);
				free(buf);
				continue;
			}
		}
#endif

		if(!dvbsub_stopped /*!dvbsub_paused*/ ) 
		{
			//sub_debug.print(Debug::VERBOSE, "[subtitles] new packet, len %d buf 0x%x pts-stc diff %lld\n", count, buf, get_pts_stc_delta(get_pts(buf)));
			/* Packet now in memory */
			packet_queue.push(buf);
			/* TODO: allocation exception */
			// wake up dvb thread
			pthread_mutex_lock(&packetMutex);
			pthread_cond_broadcast(&packetCond);
			pthread_mutex_unlock(&packetMutex);
		} 
		else 
		{
			free(buf);
			buf=NULL;
		}
	}

	dmx->Stop();
	delete dmx;
	dmx = NULL;

	sub_debug.print(Debug::VERBOSE, "%s shutdown\n", __FUNCTION__);
	pthread_exit(NULL);
}
Example #27
0
static void* dvbsub_thread(void* /*arg*/)
{
	struct timespec restartWait;
	struct timeval now;

	sub_debug.print(Debug::VERBOSE, "%s started\n", __FUNCTION__);
	if (!dvbSubtitleConverter)
		dvbSubtitleConverter = new cDvbSubtitleConverter;

	int timeout = 1000000;
	while(dvbsub_running) 
	{
		uint8_t* packet;
		int64_t pts;
		int dataoffset;
		int packlen;

		gettimeofday(&now, NULL);

		int ret = 0;
		now.tv_usec += (timeout == 0) ? 1000000 : timeout;   // add the timeout
		while (now.tv_usec >= 1000000) 
		{   
			// take care of an overflow
			now.tv_sec++;
			now.tv_usec -= 1000000;
		}
		restartWait.tv_sec = now.tv_sec;          // seconds
		restartWait.tv_nsec = now.tv_usec * 1000; // nano seconds

		pthread_mutex_lock( &packetMutex );
		ret = pthread_cond_timedwait( &packetCond, &packetMutex, &restartWait );
		pthread_mutex_unlock( &packetMutex );

		timeout = dvbSubtitleConverter->Action();

		if(packet_queue.size() == 0) {
			continue;
		}
#if 1
		sub_debug.print(Debug::VERBOSE, "PES: Wakeup, queue size %d\n\n", packet_queue.size());
#endif
		if(dvbsub_stopped /*dvbsub_paused*/) 
		{
			clear_queue();
			continue;
		}

		pthread_mutex_lock(&packetMutex);
		packet = packet_queue.pop();
		pthread_mutex_unlock(&packetMutex);

		if (!packet) {
			sub_debug.print(Debug::VERBOSE, "Error no packet found\n");
			continue;
		}
		packlen = (packet[4] << 8 | packet[5]) + 6;

		pts = get_pts(packet);

		dataoffset = packet[8] + 8 + 1;
		if (packet[dataoffset] != 0x20) 
		{
#if 1
			sub_debug.print(Debug::VERBOSE, "Not a dvb subtitle packet, discard it (len %d)\n", packlen);

			for(int i = 0; i < packlen; i++)
				printf("%02X ", packet[i]);
			printf("\n");
#endif
			goto next_round;
		}

#if 1
		sub_debug.print(Debug::VERBOSE, "PES packet: len %d data len %d PTS=%Ld (%02d:%02d:%02d.%d) diff %lld\n", packlen, packlen - (dataoffset + 2), pts, (int)(pts/324000000), (int)((pts/5400000)%60), (int)((pts/90000)%60), (int)(pts%90000), get_pts_stc_delta(pts));
#endif

		if (packlen <= dataoffset + 3) 
		{
			sub_debug.print(Debug::INFO, "Packet too short, discard\n");
			
			goto next_round;
		}

		if (packet[dataoffset + 2] == 0x0f) 
		{
			dvbSubtitleConverter->Convert(&packet[dataoffset + 2], packlen - (dataoffset + 2), pts);
		} 
		else 
		{
			sub_debug.print(Debug::INFO, "End_of_PES is missing\n");
		}
		timeout = dvbSubtitleConverter->Action();

next_round:
		free(packet);
	}

	delete dvbSubtitleConverter;

	sub_debug.print(Debug::VERBOSE, "%s shutdown\n", __FUNCTION__);
	pthread_exit(NULL);
}
Example #28
0
void AVDemuxThread::run()
{
    end = false;
    if (audio_thread && !audio_thread->isRunning())
        audio_thread->start(QThread::HighPriority);
    if (video_thread && !video_thread->isRunning())
        video_thread->start();

    int running_threads = 0;
    if (audio_thread)
        ++running_threads;
    if (video_thread)
        ++running_threads;
    qDebug("demux thread start running...%d avthreads", running_threads);

    audio_stream = demuxer->audioStream();
    video_stream = demuxer->videoStream();
    int index = 0;
    Packet pkt;
    pause(false);
    qDebug("get av queue a/v thread = %p %p", audio_thread, video_thread);
    PacketQueue *aqueue = audio_thread ? audio_thread->packetQueue() : 0;
    PacketQueue *vqueue = video_thread ? video_thread->packetQueue() : 0;
    if (aqueue) {
        aqueue->clear();
        aqueue->setBlocking(true);
    }
    if (vqueue) {
        vqueue->clear();
        vqueue->setBlocking(true);
    }
    while (!end) {
        processNextSeekTask();
#if RESUME_ONCE_ON_SEEK
        // resume once is not enough. readFrame() failed after seek (why?) and we need video packet
        processNextPauseTask();
        if (tryPause()) {
#else
        if (tryPause(ULONG_MAX)) {
#endif
            continue; //the queue is empty and will block
        }
        running_threads = (audio_thread && audio_thread->isRunning()) + (video_thread && video_thread->isRunning());
        if (!running_threads) {
            qDebug("no running avthreads. exit demuxer thread");
            break;
        }
        QMutexLocker locker(&buffer_mutex);
        Q_UNUSED(locker);
        if (end) {
            break;
        }
        if (!demuxer->readFrame()) {
            continue;
        }
        index = demuxer->stream();
        pkt = *demuxer->packet(); //TODO: how to avoid additional copy?
        //connect to stop is ok too
        if (pkt.isEnd()) {
            qDebug("read end packet %d A:%d V:%d", index, audio_stream, video_stream);
            end = true;
            //avthread can stop. do not clear queue, make sure all data are played
            if (audio_thread) {
                audio_thread->setDemuxEnded(true);
            }
            if (video_thread) {
                video_thread->setDemuxEnded(true);
            }
            break;
        }
        /*1 is empty but another is enough, then do not block to
          ensure the empty one can put packets immediatly.
          But usually it will not happen, why?
        */
        /* demux thread will be blocked only when 1 queue is full and still put
         * if vqueue is full and aqueue becomes empty, then demux thread
         * will be blocked. so we should wake up another queue when empty(or threshold?).
         * TODO: the video stream and audio stream may be group by group. provide it
         * stream data: aaaaaaavvvvvvvaaaaaaaavvvvvvvvvaaaaaa, it happens
         * stream data: aavavvavvavavavavavavavavvvaavavavava, it's ok
         */
        //TODO: use cache queue, take from cache queue if not empty?
        if (index == audio_stream) {
            /* if vqueue if not blocked and full, and aqueue is empty, then put to
             * vqueue will block demuex thread
             */
            if (aqueue) {
                if (!audio_thread || !audio_thread->isRunning()) {
                    aqueue->clear();
                    continue;
                }
                if (vqueue)
                    aqueue->blockFull(vqueue->isEnough() || demuxer->hasAttacedPicture());
                aqueue->put(pkt); //affect video_thread
            }
        } else if (index == video_stream) {
            if (!video_thread || !video_thread->isRunning()) {
                vqueue->clear();
                continue;
            }
            if (vqueue) {
                if (aqueue)
                    vqueue->blockFull(aqueue->isEnough());
                vqueue->put(pkt); //affect audio_thread
            }
        } else { //subtitle
            continue;
        }
    }
    //flush. seeking will be omitted when stopped
    if (aqueue)
        aqueue->put(Packet());
    if (vqueue)
        vqueue->put(Packet());
    while (audio_thread && audio_thread->isRunning()) {
        qDebug("waiting audio thread.......");
        audio_thread->wait(500);
    }
    while (video_thread && video_thread->isRunning()) {
        qDebug("waiting video thread.......");
        video_thread->wait(500);
    }
    qDebug("Demux thread stops running....");
}

bool AVDemuxThread::tryPause(unsigned long timeout)
{
    if (!paused)
        return false;
    QMutexLocker lock(&buffer_mutex);
    Q_UNUSED(lock);
    cond.wait(&buffer_mutex, timeout);
    return true;
}


} //namespace QtAV
static void* reader_thread(void * /*arg*/)
{
	int fds[2];
	pipe(fds);
	fcntl(fds[0], F_SETFD, FD_CLOEXEC);
	fcntl(fds[0], F_SETFL, O_NONBLOCK);
	fcntl(fds[1], F_SETFD, FD_CLOEXEC);
	fcntl(fds[1], F_SETFL, O_NONBLOCK);
	flagFd = fds[1];
	uint8_t tmp[16];  /* actually 6 should be enough */
	int count;
	int len;
	uint16_t packlen;
	uint8_t* buf;
	bool bad_startcode = false;
	set_threadname("dvbsub:reader");

	dmx = new cDemux(0);
#if HAVE_TRIPLEDRAGON
	dmx->Open(DMX_PES_CHANNEL, NULL, 16*1024);
#else
	dmx->Open(DMX_PES_CHANNEL, NULL, 64*1024);
#endif

	while (reader_running) {
		if(dvbsub_stopped /*dvbsub_paused*/) {
			sub_debug.print(Debug::VERBOSE, "%s stopped\n", __FUNCTION__);
			dmx->Stop();

			pthread_mutex_lock(&packetMutex);
			pthread_cond_broadcast(&packetCond);
			pthread_mutex_unlock(&packetMutex);

			pthread_mutex_lock(&readerMutex );
			int ret = pthread_cond_wait(&readerCond, &readerMutex);
			pthread_mutex_unlock(&readerMutex);
			if (ret) {
				sub_debug.print(Debug::VERBOSE, "pthread_cond_timedwait fails with %d\n", ret);
			}
			if(!reader_running)
				break;
			dvbsub_stopped = 0;
			sub_debug.print(Debug::VERBOSE, "%s (re)started with pid 0x%x\n", __FUNCTION__, dvbsub_pid);
		}
		if(pid_change_req) {
			pid_change_req = 0;
			clear_queue();
			dmx->Stop();
			dmx->pesFilter(dvbsub_pid);
			dmx->Start();
			sub_debug.print(Debug::VERBOSE, "%s changed to pid 0x%x\n", __FUNCTION__, dvbsub_pid);
		}

		struct pollfd pfds[2];
		pfds[0].fd = fds[1];
		pfds[0].events = POLLIN;
		char _tmp[64];

#if HAVE_SPARK_HARDWARE || HAVE_DUCKBOX_HARDWARE
		if (isEplayer) {
			poll(pfds, 1, -1);
			while (0 > read(pfds[0].fd, _tmp, sizeof(tmp)));
			continue;
		}
#endif

		pfds[1].fd = dmx->getFD();
		pfds[1].events = POLLIN;
		switch (poll(pfds, 2, -1)) {
			case 0:
			case -1:
				if (pfds[0].revents & POLLIN)
					while (0 > read(pfds[0].fd, _tmp, sizeof(tmp)));
				continue;
			default:
				if (pfds[0].revents & POLLIN)
					while (0 > read(pfds[0].fd, _tmp, sizeof(tmp)));
				if (!(pfds[1].revents & POLLIN))
					continue;
		}

		len = dmx->Read(tmp, 6, 0);
		if(len <= 0)
			continue;

		if(!memcmp(tmp, "\x00\x00\x01\xbe", 4)) { // padding stream
			packlen =  getbits(tmp, 4*8, 16) + 6;
			count = 6;
			buf = (uint8_t*) malloc(packlen);

			// actually, we're doing slightly too much here ...
			memmove(buf, tmp, 6);
			/* read rest of the packet */
			while((count < packlen) && !dvbsub_stopped) {
				len = dmx->Read(buf+count, packlen-count, 1000);
				if (len < 0) {
					break;
				} else {
					count += len;
				}
			}
			free(buf);
			buf = NULL;
			continue;
		}

		if(memcmp(tmp, "\x00\x00\x01\xbd", 4)) {
			if (!bad_startcode) {
				sub_debug.print(Debug::VERBOSE, "[subtitles] bad start code: %02x%02x%02x%02x\n", tmp[0], tmp[1], tmp[2], tmp[3]);
				bad_startcode = true;
			}
			continue;
		}
		bad_startcode = false;
		count = 6;

		packlen =  getbits(tmp, 4*8, 16) + 6;

		buf = (uint8_t*) malloc(packlen);

		memmove(buf, tmp, 6);
		/* read rest of the packet */
		while((count < packlen) && !dvbsub_stopped) {
			len = dmx->Read(buf+count, packlen-count, 1000);
			if (len < 0) {
				break;
			} else {
				count += len;
			}
		}
#if 0
		for(int i = 6; i < packlen - 4; i++) {
			if(!memcmp(&buf[i], "\x00\x00\x01\xbd", 4)) {
				int plen =  getbits(&buf[i], 4*8, 16) + 6;
				sub_debug.print(Debug::VERBOSE, "[subtitles] ******************* PES header at %d ?! *******************\n", i);
				sub_debug.print(Debug::VERBOSE, "[subtitles] start code: %02x%02x%02x%02x len %d\n", buf[i+0], buf[i+1], buf[i+2], buf[i+3], plen);
				free(buf);
				continue;
			}
		}
#endif

		if(!dvbsub_stopped /*!dvbsub_paused*/) {
			sub_debug.print(Debug::VERBOSE, "[subtitles] *** new packet, len %d buf 0x%x pts-stc diff %lld ***\n", count, buf, get_pts_stc_delta(get_pts(buf)));
			/* Packet now in memory */
			pthread_mutex_lock(&packetMutex);
			packet_queue.push(buf);
			/* TODO: allocation exception */
			// wake up dvb thread
			pthread_cond_broadcast(&packetCond);
			pthread_mutex_unlock(&packetMutex);
		} else {
			free(buf);
			buf=NULL;
		}
	}

	dmx->Stop();
	delete dmx;
	dmx = NULL;

	close(fds[0]);
	close(fds[1]);
	flagFd = -1;

	sub_debug.print(Debug::VERBOSE, "%s shutdown\n", __FUNCTION__);
	pthread_exit(NULL);
}
Example #30
0
void test_reliability_system()
{
	printf( "-----------------------------------------------------\n" );
	printf( "test reliability system\n" );
	printf( "-----------------------------------------------------\n" );

	const int MaximumSequence = 255;

	printf( "check bit index for sequence\n" );
	check( ReliabilitySystem::bit_index_for_sequence( 99, 100, MaximumSequence ) == 0 );
	check( ReliabilitySystem::bit_index_for_sequence( 90, 100, MaximumSequence ) == 9 );
	check( ReliabilitySystem::bit_index_for_sequence( 0, 1, MaximumSequence ) == 0 );
	check( ReliabilitySystem::bit_index_for_sequence( 255, 0, MaximumSequence ) == 0 );
	check( ReliabilitySystem::bit_index_for_sequence( 255, 1, MaximumSequence ) == 1 );
	check( ReliabilitySystem::bit_index_for_sequence( 254, 1, MaximumSequence ) == 2 );
	check( ReliabilitySystem::bit_index_for_sequence( 254, 2, MaximumSequence ) == 3 );

	printf( "check generate ack bits\n");
	PacketQueue packetQueue;
	for ( int i = 0; i < 32; ++i )
	{
		PacketData data;
		data.sequence = i;
		packetQueue.insert_sorted( data, MaximumSequence );
		packetQueue.verify_sorted( MaximumSequence );
	}
	check( ReliabilitySystem::generate_ack_bits( 32, packetQueue, MaximumSequence ) == 0xFFFFFFFF );
	check( ReliabilitySystem::generate_ack_bits( 31, packetQueue, MaximumSequence ) == 0x7FFFFFFF );
	check( ReliabilitySystem::generate_ack_bits( 33, packetQueue, MaximumSequence ) == 0xFFFFFFFE );
	check( ReliabilitySystem::generate_ack_bits( 16, packetQueue, MaximumSequence ) == 0x0000FFFF );
	check( ReliabilitySystem::generate_ack_bits( 48, packetQueue, MaximumSequence ) == 0xFFFF0000 );

	printf( "check generate ack bits with wrap\n");
	packetQueue.clear();
	for ( int i = 255 - 31; i <= 255; ++i )
	{
		PacketData data;
		data.sequence = i;
		packetQueue.insert_sorted( data, MaximumSequence );
		packetQueue.verify_sorted( MaximumSequence );
	}
	check( packetQueue.size() == 32 );
	check( ReliabilitySystem::generate_ack_bits( 0, packetQueue, MaximumSequence ) == 0xFFFFFFFF );
	check( ReliabilitySystem::generate_ack_bits( 255, packetQueue, MaximumSequence ) == 0x7FFFFFFF );
	check( ReliabilitySystem::generate_ack_bits( 1, packetQueue, MaximumSequence ) == 0xFFFFFFFE );
	check( ReliabilitySystem::generate_ack_bits( 240, packetQueue, MaximumSequence ) == 0x0000FFFF );
	check( ReliabilitySystem::generate_ack_bits( 16, packetQueue, MaximumSequence ) == 0xFFFF0000 );

	printf( "check process ack (1)\n" );
	{
		PacketQueue pendingAckQueue;
		for ( int i = 0; i < 33; ++i )
		{
			PacketData data;
			data.sequence = i;
			data.time = 0.0f;
			pendingAckQueue.insert_sorted( data, MaximumSequence );
			pendingAckQueue.verify_sorted( MaximumSequence );
		}
		PacketQueue ackedQueue;
		std::vector<unsigned int> acks;
		float rtt = 0.0f;
		unsigned int acked_packets = 0;
		ReliabilitySystem::process_ack( 32, 0xFFFFFFFF, pendingAckQueue, ackedQueue, acks, acked_packets, rtt, MaximumSequence );
		check( acks.size() == 33 );
		check( acked_packets == 33 );
		check( ackedQueue.size() == 33 );
		check( pendingAckQueue.size() == 0 );
		ackedQueue.verify_sorted( MaximumSequence );
		for ( unsigned int i = 0; i < acks.size(); ++i )
			check( acks[i] == i );
		unsigned int i = 0;
		for ( PacketQueue::iterator itor = ackedQueue.begin(); itor != ackedQueue.end(); ++itor, ++i )
			check( itor->sequence == i );
	}

	printf( "check process ack (2)\n" );
	{
		PacketQueue pendingAckQueue;
		for ( int i = 0; i < 33; ++i )
		{
			PacketData data;
			data.sequence = i;
			data.time = 0.0f;
			pendingAckQueue.insert_sorted( data, MaximumSequence );
			pendingAckQueue.verify_sorted( MaximumSequence );
		}
		PacketQueue ackedQueue;
		std::vector<unsigned int> acks;
		float rtt = 0.0f;
		unsigned int acked_packets = 0;
		ReliabilitySystem::process_ack( 32, 0x0000FFFF, pendingAckQueue, ackedQueue, acks, acked_packets, rtt, MaximumSequence );
		check( acks.size() == 17 );
		check( acked_packets == 17 );
		check( ackedQueue.size() == 17 );
		check( pendingAckQueue.size() == 33 - 17 );
		ackedQueue.verify_sorted( MaximumSequence );
		unsigned int i = 0;
		for ( PacketQueue::iterator itor = pendingAckQueue.begin(); itor != pendingAckQueue.end(); ++itor, ++i )
			check( itor->sequence == i );
		i = 0;
		for ( PacketQueue::iterator itor = ackedQueue.begin(); itor != ackedQueue.end(); ++itor, ++i )
			check( itor->sequence == i + 16 );
		for ( unsigned int i = 0; i < acks.size(); ++i )
			check( acks[i] == i + 16 );
	}

	printf( "check process ack (3)\n" );
	{
		PacketQueue pendingAckQueue;
		for ( int i = 0; i < 32; ++i )
		{
			PacketData data;
			data.sequence = i;
			data.time = 0.0f;
			pendingAckQueue.insert_sorted( data, MaximumSequence );
			pendingAckQueue.verify_sorted( MaximumSequence );
		}
		PacketQueue ackedQueue;
		std::vector<unsigned int> acks;
		float rtt = 0.0f;
		unsigned int acked_packets = 0;
		ReliabilitySystem::process_ack( 48, 0xFFFF0000, pendingAckQueue, ackedQueue, acks, acked_packets, rtt, MaximumSequence );
		check( acks.size() == 16 );
		check( acked_packets == 16 );
		check( ackedQueue.size() == 16 );
		check( pendingAckQueue.size() == 16 );
		ackedQueue.verify_sorted( MaximumSequence );
		unsigned int i = 0;
		for ( PacketQueue::iterator itor = pendingAckQueue.begin(); itor != pendingAckQueue.end(); ++itor, ++i )
			check( itor->sequence == i );
		i = 0;
		for ( PacketQueue::iterator itor = ackedQueue.begin(); itor != ackedQueue.end(); ++itor, ++i )
			check( itor->sequence == i + 16 );
		for ( unsigned int i = 0; i < acks.size(); ++i )
			check( acks[i] == i + 16 );
	}

	printf( "check process ack wrap around (1)\n" );
	{
		PacketQueue pendingAckQueue;
		for ( int i = 255 - 31; i <= 256; ++i )
		{
			PacketData data;
			data.sequence = i & 0xFF;
			data.time = 0.0f;
			pendingAckQueue.insert_sorted( data, MaximumSequence );
			pendingAckQueue.verify_sorted( MaximumSequence );
		}
		check( pendingAckQueue.size() == 33 );
		PacketQueue ackedQueue;
		std::vector<unsigned int> acks;
		float rtt = 0.0f;
		unsigned int acked_packets = 0;
		ReliabilitySystem::process_ack( 0, 0xFFFFFFFF, pendingAckQueue, ackedQueue, acks, acked_packets, rtt, MaximumSequence );
		check( acks.size() == 33 );
		check( acked_packets == 33 );
		check( ackedQueue.size() == 33 );
		check( pendingAckQueue.size() == 0 );
		ackedQueue.verify_sorted( MaximumSequence );
		for ( unsigned int i = 0; i < acks.size(); ++i )
			check( acks[i] == ( (i+255-31) & 0xFF ) );
		unsigned int i = 0;
		for ( PacketQueue::iterator itor = ackedQueue.begin(); itor != ackedQueue.end(); ++itor, ++i )
			check( itor->sequence == ( (i+255-31) & 0xFF ) );
	}

	printf( "check process ack wrap around (2)\n" );
	{
		PacketQueue pendingAckQueue;
		for ( int i = 255 - 31; i <= 256; ++i )
		{
			PacketData data;
			data.sequence = i & 0xFF;
			data.time = 0.0f;
			pendingAckQueue.insert_sorted( data, MaximumSequence );
			pendingAckQueue.verify_sorted( MaximumSequence );
		}
		check( pendingAckQueue.size() == 33 );
		PacketQueue ackedQueue;
		std::vector<unsigned int> acks;
		float rtt = 0.0f;
		unsigned int acked_packets = 0;
		ReliabilitySystem::process_ack( 0, 0x0000FFFF, pendingAckQueue, ackedQueue, acks, acked_packets, rtt, MaximumSequence );
		check( acks.size() == 17 );
		check( acked_packets == 17 );
		check( ackedQueue.size() == 17 );
		check( pendingAckQueue.size() == 33 - 17 );
		ackedQueue.verify_sorted( MaximumSequence );
		for ( unsigned int i = 0; i < acks.size(); ++i )
			check( acks[i] == ( (i+255-15) & 0xFF ) );
		unsigned int i = 0;
		for ( PacketQueue::iterator itor = pendingAckQueue.begin(); itor != pendingAckQueue.end(); ++itor, ++i )
			check( itor->sequence == i + 255 - 31 );
		i = 0;
		for ( PacketQueue::iterator itor = ackedQueue.begin(); itor != ackedQueue.end(); ++itor, ++i )
			check( itor->sequence == ( (i+255-15) & 0xFF ) );
	}

	printf( "check process ack wrap around (3)\n" );
	{
		PacketQueue pendingAckQueue;
		for ( int i = 255 - 31; i <= 255; ++i )
		{
			PacketData data;
			data.sequence = i & 0xFF;
			data.time = 0.0f;
			pendingAckQueue.insert_sorted( data, MaximumSequence );
			pendingAckQueue.verify_sorted( MaximumSequence );
		}
		check( pendingAckQueue.size() == 32 );
		PacketQueue ackedQueue;
		std::vector<unsigned int> acks;
		float rtt = 0.0f;
		unsigned int acked_packets = 0;
		ReliabilitySystem::process_ack( 16, 0xFFFF0000, pendingAckQueue, ackedQueue, acks, acked_packets, rtt, MaximumSequence );
		check( acks.size() == 16 );
		check( acked_packets == 16 );
		check( ackedQueue.size() == 16 );
		check( pendingAckQueue.size() == 16 );
		ackedQueue.verify_sorted( MaximumSequence );
		for ( unsigned int i = 0; i < acks.size(); ++i )
			check( acks[i] == ( (i+255-15) & 0xFF ) );
		unsigned int i = 0;
		for ( PacketQueue::iterator itor = pendingAckQueue.begin(); itor != pendingAckQueue.end(); ++itor, ++i )
			check( itor->sequence == i + 255 - 31 );
		i = 0;
		for ( PacketQueue::iterator itor = ackedQueue.begin(); itor != ackedQueue.end(); ++itor, ++i )
			check( itor->sequence == ( (i+255-15) & 0xFF ) );
	}
}