Beispiel #1
0
uint8_t get_width_height(byte *nal_sps, uint32_t *size_nal_sps, i2ctx_video **ctxVideo) {
    uint32_t width, height;
    sps_t* sps = (sps_t*)malloc(sizeof(sps_t));
    uint8_t* rbsp_buf = (uint8_t*)malloc(*size_nal_sps);

    if (nal_to_rbsp(nal_sps, (int*)size_nal_sps, rbsp_buf, (int*)size_nal_sps) < 0){
        free(rbsp_buf);
        free(sps);
        return I2ERROR_SPS_PPS;
    }
    bs_t* b = bs_new(rbsp_buf, *size_nal_sps);

    if(read_seq_parameter_set_rbsp(sps,b) < 0){
        bs_free(b);
        free(rbsp_buf);
        free(sps);
        return I2ERROR_SPS_PPS;
    }

    width = (sps->pic_width_in_mbs_minus1 + 1) * 16;
    height = (2 - sps->frame_mbs_only_flag) * (sps->pic_height_in_map_units_minus1 + 1) * 16;

    if (sps->frame_cropping_flag){
        width -= (sps->frame_crop_left_offset*2 + sps->frame_crop_right_offset*2);
        height -= (sps->frame_crop_top_offset*2 + sps->frame_crop_bottom_offset*2);
    }

    (*ctxVideo)->width = width;
    (*ctxVideo)->height = height;
    bs_free(b);
    free(rbsp_buf);
    free(sps);

    return 0;
}
	void MonoAssembly::unload()
	{
		if(!mIsLoaded)
			return;

		if(mDebugData != nullptr)
		{
			mono_debug_close_image(mMonoImage);

			bs_free(mDebugData);
			mDebugData = nullptr;
		}

		for(auto& entry : mClassesByRaw)
			bs_delete(entry.second);

		mClasses.clear();
		mClassesByRaw.clear();
		mCachedClassList.clear();

		if(mMonoImage != nullptr && !mIsDependency)
		{
			// Note: I used to call mono_image_close and mono_assembly_close here but those 
			// didn't seem to be necessary and were just crashing the program.
			mMonoImage = nullptr;
		}

		mIsLoaded = false;
		mIsDependency = false;
		mMonoAssembly = nullptr;
		mHaveCachedClassList = false;
	}
	void MonoMethod::cacheSignature() const
	{
		MonoMethodSignature* methodSignature = mono_method_signature(mMethod);

		MonoType* returnType = mono_signature_get_return_type(methodSignature);
		if (returnType != nullptr)
		{
			::MonoClass* returnClass = mono_class_from_mono_type(returnType);
			if (returnClass != nullptr)
				mCachedReturnType = MonoManager::instance().findClass(returnClass);
		}

		mCachedNumParameters = (UINT32)mono_signature_get_param_count(methodSignature);
		if (mCachedParameters != nullptr)
		{
			bs_free(mCachedParameters);
			mCachedParameters = nullptr;
		}

		if (mCachedNumParameters > 0)
		{
			mCachedParameters = (MonoClass**)bs_alloc(mCachedNumParameters * sizeof(MonoClass*));

			void* iter = nullptr;
			for (UINT32 i = 0; i < mCachedNumParameters; i++)
			{
				MonoType* curParamType = mono_signature_get_params(methodSignature, &iter);
				::MonoClass* rawClass = mono_class_from_mono_type(curParamType);
				mCachedParameters[i] = MonoManager::instance().findClass(rawClass);
			}
		}

		mIsStatic = !mono_signature_is_instance(methodSignature);
		mHasCachedSignature = true;
	}
Beispiel #4
0
	FileEncoder::~FileEncoder()
	{
		bs_free(mWriteBuffer);

		mOutputStream.close();
		mOutputStream.clear();
	}
	/**	Gets a file list from data. Caller must ensure that the data actually contains a file list. */
	Vector<Path>* Win32DropTarget::getFileListFromData(IDataObject* data)
	{
		FORMATETC fmtetc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
		STGMEDIUM stgmed;

		Vector<Path>* files = bs_new<Vector<Path>>();
		if(data->GetData(&fmtetc, &stgmed) == S_OK)
		{
			PVOID data = GlobalLock(stgmed.hGlobal);

			HDROP hDrop = (HDROP)data;
			UINT numFiles = DragQueryFileW(hDrop, 0xFFFFFFFF, nullptr, 0);

			files->resize(numFiles);
			for(UINT i = 0; i < numFiles; i++)
			{
				UINT numChars = DragQueryFileW(hDrop, i, nullptr, 0) + 1;
				wchar_t* buffer = (wchar_t*)bs_alloc((UINT32)numChars * sizeof(wchar_t));

				DragQueryFileW(hDrop, i, buffer, numChars);

				(*files)[i] = UTF8::fromWide(WString(buffer));

				bs_free(buffer);
			}

			GlobalUnlock(stgmed.hGlobal);
			ReleaseStgMedium(&stgmed);
		}

		return files;
	}
	bool checkForGLSLError(const GLuint programObj, String& outErrorMsg)
	{
		StringStream stream;

		GLint linkCompileSuccess = 0;
		glGetProgramiv(programObj, GL_LINK_STATUS, &linkCompileSuccess);
		BS_CHECK_GL_ERROR();

		if (!linkCompileSuccess && programObj > 0)
		{
			GLint infologLength = 0;
			glGetProgramiv(programObj, GL_INFO_LOG_LENGTH, &infologLength);
			BS_CHECK_GL_ERROR();

			if (infologLength > 0)
			{
				GLint charsWritten = 0;

				GLchar* infoLog = (GLchar*)bs_alloc(sizeof(GLchar)* infologLength);

				glGetProgramInfoLog(programObj, infologLength, &charsWritten, infoLog);
				BS_CHECK_GL_ERROR();

				stream << "Compile and linker info log: \n";
				stream << String(infoLog);

				bs_free(infoLog);
			}
		}

		outErrorMsg = stream.str();
		return !linkCompileSuccess;
	}
Beispiel #7
0
		~VertexConnectivity()
		{
			if (vertexFaces != nullptr)
				bs_deleteN(vertexFaces, mNumVertices);

			if (mFaces != nullptr)
				bs_free(mFaces);
		}
	VulkanDescriptorManager::~VulkanDescriptorManager()
	{
		for (auto& entry : mLayouts)
		{
			bs_delete(entry.layout);
			bs_free(entry.bindings);
		}

		for (auto& entry : mPipelineLayouts)
		{
			bs_free(entry.first.layouts);
			vkDestroyPipelineLayout(mDevice.getLogical(), entry.second, gVulkanAllocator);
		}

		for (auto& entry : mPools)
			bs_delete(entry);
	}
Beispiel #9
0
static void avl_free_node(avl_node_t *root)
{
	if(root == NULL)
		return;

	avl_free_node(root->left_child);
	avl_free_node(root->right_child);
	bs_free(root);
}
	void CmdRecordSO::clear()
	{
		mSerializedObjectSize = 0;

		if (mSerializedObject != nullptr)
		{
			bs_free(mSerializedObject);
			mSerializedObject = nullptr;
		}
	}
Beispiel #11
0
	void CmdDeleteSO::clear()
	{
		mSerializedObjectSize = 0;
		mSerializedObjectParentId = 0;

		if (mSerializedObject != nullptr)
		{
			bs_free(mSerializedObject);
			mSerializedObject = nullptr;
		}
	}
Beispiel #12
0
	String D3D11Driver::getDriverName() const
	{
		size_t size = wcslen(mAdapterIdentifier.Description);
		char* str = (char*)bs_alloc((UINT32)(size + 1));

		wcstombs(str, mAdapterIdentifier.Description, size);
		str[size] = '\0';
		String Description = str;
		
		bs_free(str);
		return String(Description );
	}
	Path FileSystem::getWorkingDirectoryPath()
	{
		char *buffer = bs_newN<char>(PATH_MAX);
		String wd;

		if (getcwd(buffer, PATH_MAX) != NULL)
			wd = buffer;
		bs_free(buffer);

		const int error = errno;
		if (error)
			LOGERR(String("Error when calling getcwd(): ") + strerror(error));

		return Path(wd);
	}
Beispiel #14
0
		void resizeFaceArray(UINT32 numFaces)
		{
			UINT32* newFaces = (UINT32*)bs_alloc(numFaces * mNumVertices * sizeof(UINT32));

			if (mFaces != nullptr)
			{
				for (UINT32 i = 0; i < mNumVertices; i++)
					memcpy(newFaces + (i * numFaces), mFaces + (i * mMaxFacesPerVertex), mMaxFacesPerVertex * sizeof(UINT32));

				bs_free(mFaces);
			}

			for (UINT32 i = 0; i < mNumVertices; i++)
				vertexFaces[i].faces = newFaces + (i * numFaces);

			mFaces = newFaces;
			mMaxFacesPerVertex = numFaces;
		}
Beispiel #15
0
	FPhysXMesh::~FPhysXMesh()
	{
		if (mCookedData != nullptr)
		{
			bs_free(mCookedData);

			mCookedData = nullptr;
			mCookedDataSize = 0;
		}

		if (mTriangleMesh != nullptr)
		{
			mTriangleMesh->release();
			mTriangleMesh = nullptr;
		}

		if (mConvexMesh != nullptr)
		{
			mConvexMesh->release();
			mConvexMesh = nullptr;
		}
	}
Beispiel #16
0
/**
 Read only the NAL headers (enough to determine unit type) from a byte buffer.
 @return unit type if read successfully, or -1 if this doesn't look like a nal
*/
int peek_nal_unit(h264_stream_t* h, uint8_t* buf, int size)
{
    nal_t* nal = h->nal;

    bs_t* b = bs_new(buf, size);

    nal->forbidden_zero_bit = bs_read_f(b,1);
    nal->nal_ref_idc = bs_read_u(b,2);
    nal->nal_unit_type = bs_read_u(b,5);

    bs_free(b);

    // basic verification, per 7.4.1
    if ( nal->forbidden_zero_bit ) { return -1; }
    if ( nal->nal_unit_type <= 0 || nal->nal_unit_type > 20 ) { return -1; }
    if ( nal->nal_unit_type > 15 && nal->nal_unit_type < 19 ) { return -1; }

    if ( nal->nal_ref_idc == 0 )
    {
        if ( nal->nal_unit_type == NAL_UNIT_TYPE_CODED_SLICE_IDR )
        {
            return -1;
        }
    }
    else 
    {
        if ( nal->nal_unit_type ==  NAL_UNIT_TYPE_SEI || 
             nal->nal_unit_type == NAL_UNIT_TYPE_AUD || 
             nal->nal_unit_type == NAL_UNIT_TYPE_END_OF_SEQUENCE || 
             nal->nal_unit_type == NAL_UNIT_TYPE_END_OF_STREAM || 
             nal->nal_unit_type == NAL_UNIT_TYPE_FILLER ) 
        {
            return -1;
        }
    }

    return nal->nal_unit_type;
}
Beispiel #17
0
int program_association_section_read(program_association_section_t *pas, uint8_t *buf, size_t buf_len, uint32_t payload_unit_start_indicator,
                                     psi_table_buffer_t *patBuffer)
{ 
   vqarray_t *programs;
   int num_programs = 0;

   if (pas == NULL || buf == NULL) 
   {
      SAFE_REPORT_TS_ERR(-1); 
      return 0;
   }

   bs_t *b = NULL;

   if (!payload_unit_start_indicator &&  patBuffer->buffer == NULL)
   {
      // this TS packet is not start of table, and we have no cached table data
      LOG_WARN ("program_association_section_read: payload_unit_start_indicator not set and no cached data");
      return 0;
   }

   if (payload_unit_start_indicator)
   {
      uint8_t payloadStartPtr = buf[0];
      buf += (payloadStartPtr + 1);
      buf_len -= (payloadStartPtr + 1);
      LOG_DEBUG_ARGS ("program_association_section_read: payloadStartPtr = %d", payloadStartPtr);
   }


   // check for pat spanning multiple TS packets
   if (patBuffer->buffer != NULL)
   {
      LOG_DEBUG_ARGS ("program_association_section_read: patBuffer detected: patBufferAllocSz = %d, patBufferUsedSz = %d", 
         patBuffer->bufferAllocSz, patBuffer->bufferUsedSz);
      size_t numBytesToCopy = buf_len;
      if (buf_len > (patBuffer->bufferAllocSz - patBuffer->bufferUsedSz))
      {
         numBytesToCopy = patBuffer->bufferAllocSz - patBuffer->bufferUsedSz;
      }
         
      LOG_DEBUG_ARGS ("program_association_section_read: copying %d bytes to patBuffer", numBytesToCopy);
      memcpy (patBuffer->buffer + patBuffer->bufferUsedSz, buf, numBytesToCopy);
      patBuffer->bufferUsedSz += numBytesToCopy;
      
      if (patBuffer->bufferUsedSz < patBuffer->bufferAllocSz)
      {
         LOG_DEBUG ("program_association_section_read: patBuffer not yet full -- returning");
         return 0;
      }

      b = bs_new(patBuffer->buffer, patBuffer->bufferUsedSz);
   }
   else
   {
      b = bs_new(buf, buf_len);
   }
      

   pas->table_id = bs_read_u8(b); 
   if (pas->table_id != program_association_section) 
   {
      LOG_ERROR_ARGS("Table ID in PAT is 0x%02X instead of expected 0x%02X", 
                     pas->table_id, program_association_section); 
      reportAddErrorLogArgs("Table ID in PAT is 0x%02X instead of expected 0x%02X", 
                     pas->table_id, program_association_section); 
      SAFE_REPORT_TS_ERR(-30); 
      resetPSITableBuffer(patBuffer);
      bs_free (b);
      return 0;
   }
   
   // read byte 0
   
   pas->section_syntax_indicator = bs_read_u1(b); 
   if (!pas->section_syntax_indicator) 
   {
      LOG_ERROR("section_syntax_indicator not set in PAT"); 
      reportAddErrorLog("section_syntax_indicator not set in PAT"); 
      SAFE_REPORT_TS_ERR(-31); 
      resetPSITableBuffer(patBuffer);
      bs_free (b);
      return 0;
   }
   bs_skip_u(b, 3); // TODO read the zero bit, check it to be zero
   pas->section_length = bs_read_u(b, 12); 
   if (pas->section_length > MAX_SECTION_LEN) 
   {
      LOG_ERROR_ARGS("PAT section length is 0x%02X, larger than maximum allowed 0x%02X", 
                     pas->section_length, MAX_SECTION_LEN); 
      reportAddErrorLogArgs("PAT section length is 0x%02X, larger than maximum allowed 0x%02X", 
                     pas->section_length, MAX_SECTION_LEN); 
      SAFE_REPORT_TS_ERR(-32); 
      resetPSITableBuffer(patBuffer);
      bs_free (b);
      return 0;
   }
   
   if (pas->section_length > bs_bytes_left(b))
   {
      LOG_DEBUG ("program_association_section_read: Detected section spans more than one TS packet -- allocating buffer");

      if (patBuffer->buffer != NULL)
      {
         // should never get here
         LOG_ERROR ("program_association_section_read: unexpected patBufffer");
         reportAddErrorLog ("program_association_section_read: unexpected patBufffer");
         resetPSITableBuffer(patBuffer);
      }

      patBuffer->bufferAllocSz = pas->section_length + 3;
      patBuffer->buffer = (uint8_t *)calloc (pas->section_length + 3, 1);
      memcpy (patBuffer->buffer, buf, buf_len);
      patBuffer->bufferUsedSz = buf_len;

      bs_free (b);
      return 0;
   }

   // read bytes 1,2
   
   pas->transport_stream_id = bs_read_u16(b); 
   
   // read bytes 3,4
   
   bs_skip_u(b, 2); 
   pas->version_number = bs_read_u(b, 5); 
   pas->current_next_indicator = bs_read_u1(b); 
   if (!pas->current_next_indicator) LOG_WARN("This PAT is not yet applicable/n"); 
   
   // read byte 5
   
   pas->section_number = bs_read_u8(b); 
   pas->last_section_number = bs_read_u8(b); 
   if (pas->section_number != 0 || pas->last_section_number != 0) LOG_WARN("Multi-section PAT is not supported yet/n"); 
   
   // read bytes 6,7
   
   num_programs = (pas->section_length - 5 - 4) / 4;  // Programs listed in the PAT
   // explanation: section_length gives us the length from the end of section_length
   // we used 5 bytes for the mandatory section fields, and will use another 4 bytes for CRC
   // the remaining bytes contain program information, which is 4 bytes per iteration
   // It's much shorter in C :-)

   // Read the program loop, but ignore the NIT PID "program"
   programs = vqarray_new();
   for (uint32_t i = 0; i < num_programs; i++)
   {
      program_info_t *prog = malloc(sizeof(program_info_t));
      prog->program_number = bs_read_u16(b);
      if (prog->program_number == 0) { // Skip the NIT PID program (not a real program)
         free(prog);
         bs_skip_u(b, 16);
         continue;
      }
      bs_skip_u(b, 3);
      prog->program_map_PID = bs_read_u(b, 13);
      vqarray_add(programs, (vqarray_elem_t*)prog);
   }

   // This is our true number of programs
   pas->_num_programs = vqarray_length(programs);
   
   if (pas->_num_programs > 1) LOG_WARN_ARGS("%zd programs found, but only SPTS is fully supported. Patches are welcome.", pas->_num_programs); 
   
   // Copy form our vqarray into the native array
   pas->programs = malloc(pas->_num_programs * sizeof(program_info_t)); 
   for (uint32_t i = 0; i < pas->_num_programs; i++) 
   {
      program_info_t* prog = (program_info_t*)vqarray_pop(programs);
      pas->programs[i] = *prog;
      free(prog);
   }
   vqarray_free(programs);
   
   pas->CRC_32 = bs_read_u32(b); 
   
   // check CRC
   crc_t pas_crc = crc_init(); 
   pas_crc = crc_update(pas_crc, buf, bs_pos(b) - 4); 
   pas_crc = crc_finalize(pas_crc); 
   if (pas_crc != pas->CRC_32) 
   {
      LOG_ERROR_ARGS("PAT CRC_32 specified as 0x%08X, but calculated as 0x%08X", pas->CRC_32, pas_crc); 
      reportAddErrorLogArgs("PAT CRC_32 specified as 0x%08X, but calculated as 0x%08X", pas->CRC_32, pas_crc); 
      SAFE_REPORT_TS_ERR(-33); 
      resetPSITableBuffer(patBuffer);
      bs_free (b);
      return 0;
   } 
   else 
   {
      // LOG_DEBUG("PAT CRC_32 checked successfully");
      // don't enable unless you want to see this every ~100ms
   }
   

   bs_free(b); 
            
   resetPSITableBuffer(patBuffer);

   return 1;
}
	SPtr<Resource> FMODImporter::import(const Path& filePath, SPtr<const ImportOptions> importOptions)
	{
		WString extension = filePath.getWExtension();
		StringUtil::toLowerCase(extension);

		AudioFileInfo info;

		FMOD::Sound* sound;
		String pathStr = filePath.toString();
		if(gFMODAudio()._getFMOD()->createSound(pathStr.c_str(), FMOD_CREATESAMPLE, nullptr, &sound) != FMOD_OK)
		{
			LOGERR("Failed importing audio file: " + pathStr);
			return nullptr;
		}

		FMOD_SOUND_FORMAT format;
		INT32 numChannels = 0;
		INT32 numBits = 0;

		sound->getFormat(nullptr, &format, &numChannels, &numBits);

		if(format != FMOD_SOUND_FORMAT_PCM8 && format != FMOD_SOUND_FORMAT_PCM16 && format != FMOD_SOUND_FORMAT_PCM24 
			&& format != FMOD_SOUND_FORMAT_PCM32 && format != FMOD_SOUND_FORMAT_PCMFLOAT)
		{
			LOGERR("Failed importing audio file, invalid imported format: " + pathStr);
			return nullptr;
		}

		float frequency = 0.0f;
		sound->getDefaults(&frequency, nullptr);

		UINT32 size;
		sound->getLength(&size, FMOD_TIMEUNIT_PCMBYTES);
		
		info.bitDepth = numBits;
		info.numChannels = numChannels;
		info.sampleRate = (UINT32)frequency;
		info.numSamples = size / (info.bitDepth / 8);

		UINT32 bytesPerSample = info.bitDepth / 8;
		UINT32 bufferSize = info.numSamples * bytesPerSample;
		UINT8* sampleBuffer = (UINT8*)bs_alloc(bufferSize);
		assert(bufferSize == size);
		
		UINT8* startData = nullptr;
		UINT8* endData = nullptr;
		UINT32 startSize = 0;
		UINT32 endSize = 0;
		sound->lock(0, size, (void**)&startData, (void**)&endData, &startSize, &endSize);

		if(format == FMOD_SOUND_FORMAT_PCMFLOAT)
		{
			assert(info.bitDepth == 32);

			UINT32* output = (UINT32*)sampleBuffer;
			for(UINT32 i = 0; i < info.numSamples; i++)
			{
				float value = *(((float*)startData) + i);
				*output = (UINT32)(value * 2147483647.0f);
				output++;
			}
		}
		else
		{
			memcpy(sampleBuffer, startData, bufferSize);
		}

		sound->unlock((void**)&startData, (void**)&endData, startSize, endSize);
		sound->release();

		SPtr<const AudioClipImportOptions> clipIO = std::static_pointer_cast<const AudioClipImportOptions>(importOptions);

		// If 3D, convert to mono
		if (clipIO->getIs3D() && info.numChannels > 1)
		{
			UINT32 numSamplesPerChannel = info.numSamples / info.numChannels;

			UINT32 monoBufferSize = numSamplesPerChannel * bytesPerSample;
			UINT8* monoBuffer = (UINT8*)bs_alloc(monoBufferSize);

			AudioUtility::convertToMono(sampleBuffer, monoBuffer, info.bitDepth, numSamplesPerChannel, info.numChannels);

			info.numSamples = numSamplesPerChannel;
			info.numChannels = 1;

			bs_free(sampleBuffer);

			sampleBuffer = monoBuffer;
			bufferSize = monoBufferSize;
		}

		// Convert bit depth if needed
		if (clipIO->getBitDepth() != info.bitDepth)
		{
			UINT32 outBufferSize = info.numSamples * (clipIO->getBitDepth() / 8);
			UINT8* outBuffer = (UINT8*)bs_alloc(outBufferSize);

			AudioUtility::convertBitDepth(sampleBuffer, info.bitDepth, outBuffer, clipIO->getBitDepth(), info.numSamples);

			info.bitDepth = clipIO->getBitDepth();

			bs_free(sampleBuffer);

			sampleBuffer = outBuffer;
			bufferSize = outBufferSize;
		}

		// Encode to Ogg Vorbis if needed
		if (clipIO->getFormat() == AudioFormat::VORBIS)
		{



			// TODO - Encode to Ogg Vorbis!




		}

		SPtr<MemoryDataStream> sampleStream = bs_shared_ptr_new<MemoryDataStream>(sampleBuffer, bufferSize);

		AUDIO_CLIP_DESC clipDesc;
		clipDesc.bitDepth = info.bitDepth;
		clipDesc.format = clipIO->getFormat();
		clipDesc.frequency = info.sampleRate;
		clipDesc.numChannels = info.numChannels;
		clipDesc.readMode = clipIO->getReadMode();
		clipDesc.is3D = clipIO->getIs3D();

		SPtr<AudioClip> clip = AudioClip::_createPtr(sampleStream, bufferSize, info.numSamples, clipDesc);

		WString fileName = filePath.getWFilename(false);
		clip->setName(fileName);

		return clip;
	}
	ScriptSerializedSceneObject::~ScriptSerializedSceneObject()
	{
		if (mSerializedObject != nullptr)
			bs_free(mSerializedObject);
	}
Beispiel #20
0
//7.3.1 NAL unit syntax
int structure(nal_unit)(h264_stream_t* h, uint8_t* buf, int size)
{
    nal_t* nal = h->nal;

    int nal_size = size;
    int rbsp_size = size;
    uint8_t* rbsp_buf = (uint8_t*)calloc(1, rbsp_size);

    if( is_reading )
    {
        int rc = nal_to_rbsp(buf, &nal_size, rbsp_buf, &rbsp_size);

        if (rc < 0) {
            free(rbsp_buf);    // handle conversion error
            return -1;
        }
    }

    if( is_writing )
    {
        rbsp_size = size*3/4; // NOTE this may have to be slightly smaller (3/4 smaller, worst case) in order to be guaranteed to fit
    }

    bs_t* b = bs_new(rbsp_buf, rbsp_size);
    value( forbidden_zero_bit, f(1, 0) );
    value( nal->nal_ref_idc, u(2) );
    value( nal->nal_unit_type, u(5) );

    switch ( nal->nal_unit_type )
    {
    case NAL_UNIT_TYPE_CODED_SLICE_IDR:
    case NAL_UNIT_TYPE_CODED_SLICE_NON_IDR:
    case NAL_UNIT_TYPE_CODED_SLICE_AUX:
        structure(slice_layer_rbsp)(h, b);
        break;

#ifdef HAVE_SEI
    case NAL_UNIT_TYPE_SEI:
        structure(sei_rbsp)(h, b);
        break;
#endif

    case NAL_UNIT_TYPE_SPS:
        structure(seq_parameter_set_rbsp)(h, b);
        break;

    case NAL_UNIT_TYPE_PPS:
        structure(pic_parameter_set_rbsp)(h, b);
        break;

    case NAL_UNIT_TYPE_AUD:
        structure(access_unit_delimiter_rbsp)(h, b);
        break;

    case NAL_UNIT_TYPE_END_OF_SEQUENCE:
        structure(end_of_seq_rbsp)(h, b);
        break;

    case NAL_UNIT_TYPE_END_OF_STREAM:
        structure(end_of_stream_rbsp)(h, b);
        break;

    case NAL_UNIT_TYPE_FILLER:
    case NAL_UNIT_TYPE_SPS_EXT:
    case NAL_UNIT_TYPE_UNSPECIFIED:
    case NAL_UNIT_TYPE_CODED_SLICE_DATA_PARTITION_A:
    case NAL_UNIT_TYPE_CODED_SLICE_DATA_PARTITION_B:
    case NAL_UNIT_TYPE_CODED_SLICE_DATA_PARTITION_C:
    default:
        return -1;
    }

    if (bs_overrun(b)) {
        bs_free(b);
        free(rbsp_buf);
        return -1;
    }

    if( is_writing )
    {
        // now get the actual size used
        rbsp_size = bs_pos(b);

        int rc = rbsp_to_nal(rbsp_buf, &rbsp_size, buf, &nal_size);
        if (rc < 0) {
            bs_free(b);
            free(rbsp_buf);
            return -1;
        }
    }

    bs_free(b);
    free(rbsp_buf);

    return nal_size;
}
Beispiel #21
0
void hl_free(hardlocation* hl) {
	bs_free(hl->address);
	free(hl->adder);
	free(hl);
}
int program_map_section_read(program_map_section_t *pms, uint8_t *buf, size_t buf_size) {
	if (pms == NULL || buf == NULL) {
		SAFE_REPORT_TS_ERR(-1);
		return 0;
	}

	bs_t *b = bs_new(buf, buf_size);

	pms->table_id = bs_read_u8(b);
	if (pms->table_id != TS_program_map_section) {
		LOG_ERROR_ARGS("Table ID in PMT is 0x%02X instead of expected 0x%02X", pms->table_id, TS_program_map_section);
		SAFE_REPORT_TS_ERR(-40);
		return 0;
	}

	pms->section_syntax_indicator = bs_read_u1(b);
	if (!pms->section_syntax_indicator) {
		LOG_ERROR("section_syntax_indicator not set in PMT");
		SAFE_REPORT_TS_ERR(-41);
		return 0;
	}

	bs_skip_u(b, 3);
	pms->section_length = bs_read_u(b, 12);
	if (pms->section_length > MAX_SECTION_LEN) {
		LOG_ERROR_ARGS("PMT section length is 0x%02X, larger than maximum allowed 0x%02X",
			pms->section_length, MAX_SECTION_LEN);
		SAFE_REPORT_TS_ERR(-42);
		return 0;
	}

	int section_start = bs_pos(b);

	// bytes 0,1
	pms->program_number = bs_read_u16(b);

	// byte 2;
	bs_skip_u(b, 2);
	pms->version_number = bs_read_u(b, 5);
	pms->current_next_indicator = bs_read_u1(b);
	if (!pms->current_next_indicator)
		LOG_WARN("This PMT is not yet applicable/n");

	// bytes 3,4
	pms->section_number = bs_read_u8(b);
	pms->last_section_number = bs_read_u8(b);
	if (pms->section_number != 0 || pms->last_section_number != 0) {
		LOG_ERROR("Multi-section PMT is not allowed/n");
		SAFE_REPORT_TS_ERR(-43);
		return 0;
	}

	bs_skip_u(b, 3);
	pms->PCR_PID = bs_read_u(b, 13);
	if (pms->PCR_PID < GENERAL_PURPOSE_PID_MIN || pms->PCR_PID > GENERAL_PURPOSE_PID_MAX) {
		LOG_ERROR_ARGS("PCR PID has invalid value 0x%02X", pms->PCR_PID);
		SAFE_REPORT_TS_ERR(-44);
		return 0;
	}
	bs_skip_u(b, 4);

	pms->program_info_length = bs_read_u(b, 12);
	if (pms->program_info_length > MAX_PROGRAM_INFO_LEN) {
		LOG_ERROR_ARGS("PMT program info length is 0x%02X, larger than maximum allowed 0x%02X",
			pms->program_info_length, MAX_PROGRAM_INFO_LEN);
		SAFE_REPORT_TS_ERR(-45);
		return 0;
	}

	read_descriptor_loop(pms->descriptors, b, pms->program_info_length);

	while (pms->section_length - (bs_pos(b) - section_start) > 4) { // account for CRC
		elementary_stream_info_t *es = es_info_new();
		es_info_read(es, b);
		vqarray_add(pms->es_info, es);
	}

	pms->CRC_32 = bs_read_u32(b);

	// check CRC
	crc_t pas_crc = crc_init();
	pas_crc = crc_update(pas_crc, buf, bs_pos(b) - 4);
	pas_crc = crc_finalize(pas_crc);
	if (pas_crc != pms->CRC_32) {
		LOG_ERROR_ARGS("PMT CRC_32 specified as 0x%08X, but calculated as 0x%08X", pms->CRC_32, pas_crc);
		SAFE_REPORT_TS_ERR(-46);
		return 0;
	} else {
		LOG_DEBUG("PMT CRC_32 checked successfully");
	}

	int bytes_read = bs_pos(b);
	bs_free(b);

	return bytes_read;
}
int program_association_section_read(program_association_section_t *pas, uint8_t *buf, size_t buf_len) {
	if (pas == NULL || buf == NULL) {
		SAFE_REPORT_TS_ERR(-1);
		return 0;
	}

	bs_t *b = bs_new(buf, buf_len);

	pas->table_id = bs_read_u8(b);
	if (pas->table_id != program_association_section) {
		LOG_ERROR_ARGS("Table ID in PAT is 0x%02X instead of expected 0x%02X",
			pas->table_id, program_association_section);
		SAFE_REPORT_TS_ERR(-30);
		return 0;
	}

	// read byte 0

	pas->section_syntax_indicator = bs_read_u1(b);
	if (!pas->section_syntax_indicator) {
		LOG_ERROR("section_syntax_indicator not set in PAT");
		SAFE_REPORT_TS_ERR(-31);
		return 0;
	}
	bs_skip_u(b, 3); // TODO read the zero bit, check it to be zero
	pas->section_length = bs_read_u(b, 12);
	if (pas->section_length > MAX_SECTION_LEN) {
		LOG_ERROR_ARGS("PAT section length is 0x%02X, larger than maximum allowed 0x%02X",
			pas->section_length, MAX_SECTION_LEN);
		SAFE_REPORT_TS_ERR(-32);
		return 0;
	}

	// read bytes 1,2

	pas->transport_stream_id = bs_read_u16(b);

	// read bytes 3,4

	bs_skip_u(b, 2);
	pas->version_number = bs_read_u(b, 5);
	pas->current_next_indicator = bs_read_u1(b);
	if (!pas->current_next_indicator)
		LOG_WARN("This PAT is not yet applicable/n");

	// read byte 5

	pas->section_number = bs_read_u8(b);
	pas->last_section_number = bs_read_u8(b);
	if (pas->section_number != 0 || pas->last_section_number != 0)
		LOG_WARN("Multi-section PAT is not supported yet/n");

	// read bytes 6,7

	pas->_num_programs = (pas->section_length - 5 - 4) / 4;
	// explanation: section_length gives us the length from the end of section_length
	// we used 5 bytes for the mandatory section fields, and will use another 4 bytes for CRC
	// the remaining bytes contain program information, which is 4 bytes per iteration
	// It's much shorter in C :-)

	if (pas->_num_programs > 1)
		LOG_WARN_ARGS("%zd programs found, but only SPTS is fully supported. Patches are welcome.", pas->_num_programs);

	pas->programs = malloc(pas->_num_programs * sizeof(program_info_t));
	for (uint32_t i = 0; i < pas->_num_programs; i++) {
		pas->programs[i].program_number = bs_read_u16(b);
		bs_skip_u(b, 3);
		pas->programs[i].program_map_PID = bs_read_u(b, 13);
	}

	pas->CRC_32 = bs_read_u32(b);

	// check CRC
	crc_t pas_crc = crc_init();
	pas_crc = crc_update(pas_crc, buf, bs_pos(b) - 4);
	pas_crc = crc_finalize(pas_crc);
	if (pas_crc != pas->CRC_32) {
		LOG_ERROR_ARGS("PAT CRC_32 specified as 0x%08X, but calculated as 0x%08X", pas->CRC_32, pas_crc);
		SAFE_REPORT_TS_ERR(-33);
		return 0;
	} else {
		LOG_DEBUG("PAT CRC_32 checked successfully");
	}

	bs_free(b);
	return 1;
}
Beispiel #24
0
	MonoMethod::~MonoMethod()
	{
		if (mCachedParameters != nullptr)
			bs_free(mCachedParameters);
	}
Beispiel #25
0
static avl_node_t* avl_remove_node(
	bs_avl_t* avl, 
	avl_node_t *parent, 
	avl_data_t data)
{
	avl_node_t* toRemove = NULL;
	avl_node_t* next = NULL;
	if(NULL == avl || NULL == avl->compare)
		return NULL;

	if(NULL == parent)
	{
		bs_debug("not found! \n");
		return NULL;
	}

	if(avl->compare(parent->data, data) < 0)
	{
		parent->right_child = avl_remove_node(avl, parent->right_child, data);
		return avl_rebalance(parent);
	}
	else if(avl->compare(parent->data, data) > 0)
	{
		parent->left_child = avl_remove_node(avl, parent->left_child, data);
		return avl_rebalance(parent);
	}
	else
	{
		bs_debug("remove :%d \n", parent->data);
		if(!parent->left_child && !parent->right_child)
		{
			bs_free((void*)parent);
			parent = NULL;
		}
		else if(!parent->left_child)
		{
			toRemove = parent;
			parent = parent->right_child;
			bs_free((void*)toRemove);

		}
		else if(!parent->right_child)
		{
			toRemove = parent;
			parent = parent->left_child;
			bs_free((void*)toRemove);
		}
		else
		{
			toRemove = parent;
			next = toRemove->right_child;
			if(next->left_child == NULL)
			{
				parent = next;
				parent->left_child = toRemove->left_child;
			}
			else
			{
				while(next->left_child->left_child)
					next = next->left_child;
				parent = next->left_child;
				next->left_child = parent->right_child;
				
				parent->left_child = toRemove->left_child;
				parent->right_child = toRemove->right_child;
			}

			bs_free(toRemove);
		}

		return avl_rebalance(parent);
	}
}
	GpuParamBlockBuffer::~GpuParamBlockBuffer()
	{
		if (mCachedData != nullptr)
			bs_free(mCachedData);
	}
Beispiel #27
0
int program_map_section_read(program_map_section_t *pms, uint8_t *buf, size_t buf_size, uint32_t payload_unit_start_indicator,
   psi_table_buffer_t *pmtBuffer) 
{ 
   LOG_DEBUG ("program_map_section_read -- entering");
   if (pms == NULL || buf == NULL) 
   {
      SAFE_REPORT_TS_ERR(-1); 
      return 0;
   }

   bs_t *b = NULL;

   if (!payload_unit_start_indicator &&  pmtBuffer->buffer == NULL)
   {
      // this TS packet is not start of table, and we have no cached table data
      LOG_WARN ("program_map_section_read: payload_unit_start_indicator not set and no cached data");
      return 0;
   }

   if (payload_unit_start_indicator)
   {
      uint8_t payloadStartPtr = buf[0];
      buf += (payloadStartPtr + 1);
      buf_size -= (payloadStartPtr + 1);
      LOG_DEBUG_ARGS ("program_map_section_read: payloadStartPtr = %d", payloadStartPtr);
   }

   // check for pmt spanning multiple TS packets
   if (pmtBuffer->buffer != NULL)
   {
      LOG_DEBUG_ARGS ("program_map_section_read: pmtBuffer detected: pmtBufferAllocSz = %d, pmtBufferUsedSz = %d", pmtBuffer->bufferAllocSz, pmtBuffer->bufferUsedSz);
      size_t numBytesToCopy = buf_size;
      if (buf_size > (pmtBuffer->bufferAllocSz - pmtBuffer->bufferUsedSz))
      {
         numBytesToCopy = pmtBuffer->bufferAllocSz - pmtBuffer->bufferUsedSz;
      }
         
      LOG_DEBUG_ARGS ("program_map_section_read: copying %d bytes to pmtBuffer", numBytesToCopy);
      memcpy (pmtBuffer->buffer + pmtBuffer->bufferUsedSz, buf, numBytesToCopy);
      pmtBuffer->bufferUsedSz += numBytesToCopy;
      
      if (pmtBuffer->bufferUsedSz < pmtBuffer->bufferAllocSz)
      {
         LOG_DEBUG ("program_map_section_read: pmtBuffer not yet full -- returning");
         return 0;
      }

      b = bs_new(pmtBuffer->buffer, pmtBuffer->bufferUsedSz);
   }
   else
   {
      b = bs_new(buf, buf_size);
   }
      
   pms->table_id = bs_read_u8(b); 
   if (pms->table_id != TS_program_map_section) 
   {
      LOG_ERROR_ARGS("Table ID in PMT is 0x%02X instead of expected 0x%02X", pms->table_id, TS_program_map_section); 
      reportAddErrorLogArgs("Table ID in PMT is 0x%02X instead of expected 0x%02X", pms->table_id, TS_program_map_section); 
      SAFE_REPORT_TS_ERR(-40);
      resetPSITableBuffer(pmtBuffer);
      bs_free (b);
      return 0;
   }

   pms->section_syntax_indicator = bs_read_u1(b); 
   if (!pms->section_syntax_indicator) 
   {
      LOG_ERROR("section_syntax_indicator not set in PMT"); 
      reportAddErrorLog("section_syntax_indicator not set in PMT"); 
      SAFE_REPORT_TS_ERR(-41); 
      resetPSITableBuffer(pmtBuffer);
      bs_free (b);
      return 0;
   }
   
   bs_skip_u(b, 3); 

   pms->section_length = bs_read_u(b, 12); 
   if (pms->section_length > MAX_SECTION_LEN) 
   {
      LOG_ERROR_ARGS("PMT section length is 0x%02X, larger than maximum allowed 0x%02X", 
                     pms->section_length, MAX_SECTION_LEN); 
      reportAddErrorLogArgs("PMT section length is 0x%02X, larger than maximum allowed 0x%02X", 
                     pms->section_length, MAX_SECTION_LEN); 
      SAFE_REPORT_TS_ERR(-42); 
      resetPSITableBuffer(pmtBuffer);
      bs_free (b);
      return 0;
   }

   if (pms->section_length > bs_bytes_left(b))
   {
      LOG_DEBUG ("program_map_section_read: Detected section spans more than one TS packet -- allocating buffer");

      if (pmtBuffer->buffer != NULL)
      {
         // should never get here
         LOG_ERROR ("program_map_section_read: unexpected pmtBufffer");
         reportAddErrorLog ("program_map_section_read: unexpected pmtBufffer");
         resetPSITableBuffer(pmtBuffer);
      }

      pmtBuffer->bufferAllocSz = pms->section_length + 3;
      pmtBuffer->buffer = (uint8_t *)calloc (pms->section_length + 3, 1);
      memcpy (pmtBuffer->buffer, buf, buf_size);
      pmtBuffer->bufferUsedSz = buf_size;

      bs_free (b);
      return 0;
   }

   int section_start = bs_pos(b); 
   
   // bytes 0,1
   pms->program_number = bs_read_u16(b); 
   
   // byte 2;
   bs_skip_u(b, 2); 
   pms->version_number = bs_read_u(b, 5); 
   pms->current_next_indicator = bs_read_u1(b); 
   if (!pms->current_next_indicator) LOG_WARN("This PMT is not yet applicable/n"); 
   
   // bytes 3,4
   pms->section_number = bs_read_u8(b); 
   pms->last_section_number = bs_read_u8(b); 
   if (pms->section_number != 0 || pms->last_section_number != 0) 
   {
      LOG_ERROR("Multi-section PMT is not allowed/n"); 
      reportAddErrorLog("Multi-section PMT is not allowed/n"); 
      SAFE_REPORT_TS_ERR(-43); 
      resetPSITableBuffer(pmtBuffer);
      bs_free (b);
      return 0;
   }
   
   bs_skip_u(b, 3); 
   pms->PCR_PID = bs_read_u(b, 13); 
   if (pms->PCR_PID < GENERAL_PURPOSE_PID_MIN || pms->PCR_PID > GENERAL_PURPOSE_PID_MAX) 
   {
      LOG_ERROR_ARGS("PCR PID has invalid value 0x%02X", pms->PCR_PID); 
      reportAddErrorLogArgs("PCR PID has invalid value 0x%02X", pms->PCR_PID); 
      SAFE_REPORT_TS_ERR(-44); 
      resetPSITableBuffer(pmtBuffer);
      bs_free (b);
      return 0;
   }
 //  printf ("PCR PID = %d\n", pms->PCR_PID);
   bs_skip_u(b, 4); 
   
   pms->program_info_length = bs_read_u(b, 12); 
   if (pms->program_info_length > MAX_PROGRAM_INFO_LEN) 
   {
      LOG_ERROR_ARGS("PMT program info length is 0x%02X, larger than maximum allowed 0x%02X", 
                     pms->program_info_length, MAX_PROGRAM_INFO_LEN); 
      reportAddErrorLogArgs("PMT program info length is 0x%02X, larger than maximum allowed 0x%02X", 
                     pms->program_info_length, MAX_PROGRAM_INFO_LEN); 
      SAFE_REPORT_TS_ERR(-45); 
      resetPSITableBuffer(pmtBuffer);
      bs_free (b);
      return 0;
   }
   
   read_descriptor_loop(pms->descriptors, b, pms->program_info_length); 

   while (!bs_eof(b) && pms->section_length - (bs_pos(b) - section_start) > 4) // account for CRC
   {
      elementary_stream_info_t *es = es_info_new();
      es_info_read(es, b); 
      vqarray_add(pms->es_info, es);
   }
   
   pms->CRC_32 = bs_read_u32(b); 
   
   // check CRC
   crc_t pas_crc = crc_init(); 
   pas_crc = crc_update(pas_crc, b->start, bs_pos(b) - 4); 
   pas_crc = crc_finalize(pas_crc); 
   if (pas_crc != pms->CRC_32) 
   {
      LOG_ERROR_ARGS("PMT CRC_32 specified as 0x%08X, but calculated as 0x%08X", pms->CRC_32, pas_crc); 
      reportAddErrorLogArgs("PMT CRC_32 specified as 0x%08X, but calculated as 0x%08X", pms->CRC_32, pas_crc); 
      SAFE_REPORT_TS_ERR(-46); 
      resetPSITableBuffer(pmtBuffer);
      bs_free (b);
      return 0;
   } 
   else 
   {
      // LOG_DEBUG("PMT CRC_32 checked successfully");
   }
   
   int bytes_read = bs_pos(b); 
   bs_free(b); 

   resetPSITableBuffer(pmtBuffer);

   return bytes_read;
}
Beispiel #28
0
int conditional_access_section_read(conditional_access_section_t *cas, uint8_t *buf, size_t buf_len, uint32_t payload_unit_start_indicator,
                                    psi_table_buffer_t *catBuffer) 
{ 
   if (cas == NULL || buf == NULL) 
   {
      SAFE_REPORT_TS_ERR(-1); 
      return 0;
   }
   
   bs_t *b = NULL;

   if (!payload_unit_start_indicator &&  catBuffer->buffer == NULL)
   {
      // this TS packet is not start of table, and we have no cached table data
      LOG_WARN ("conditional_access_section_read: payload_unit_start_indicator not set and no cached data");
      return 0;
   }

   if (payload_unit_start_indicator)
   {
      uint8_t payloadStartPtr = buf[0];
      buf += (payloadStartPtr + 1);
      buf_len -= (payloadStartPtr + 1);
      LOG_DEBUG_ARGS ("conditional_access_section_read: payloadStartPtr = %d", payloadStartPtr);
   }

   // check for pat spanning multiple TS packets
   if (catBuffer->buffer != NULL)
   {
      LOG_DEBUG_ARGS ("conditional_access_section_read: catBuffer detected: catBufferAllocSz = %d, catBufferUsedSz = %d", 
         catBuffer->bufferAllocSz, catBuffer->bufferUsedSz);
      size_t numBytesToCopy = buf_len;
      if (buf_len > (catBuffer->bufferAllocSz - catBuffer->bufferUsedSz))
      {
         numBytesToCopy = catBuffer->bufferAllocSz - catBuffer->bufferUsedSz;
      }
         
      LOG_DEBUG_ARGS ("conditional_access_section_read: copying %d bytes to catBuffer", numBytesToCopy);
      memcpy (catBuffer->buffer + catBuffer->bufferUsedSz, buf, numBytesToCopy);
      catBuffer->bufferUsedSz += numBytesToCopy;
      
      if (catBuffer->bufferUsedSz < catBuffer->bufferAllocSz)
      {
         LOG_DEBUG ("conditional_access_section_read: catBuffer not yet full -- returning");
         return 0;
      }

      b = bs_new(catBuffer->buffer, catBuffer->bufferUsedSz);
   }
   else
   {
      b = bs_new(buf, buf_len);
   }
         
   cas->table_id = bs_read_u8(b); 
   if (cas->table_id != conditional_access_section) 
   {
      LOG_ERROR_ARGS("Table ID in CAT is 0x%02X instead of expected 0x%02X", 
                     cas->table_id, conditional_access_section); 
      reportAddErrorLogArgs("Table ID in CAT is 0x%02X instead of expected 0x%02X", 
                     cas->table_id, conditional_access_section); 
      SAFE_REPORT_TS_ERR(-30); 
      resetPSITableBuffer(catBuffer);
      bs_free (b);
      return 0;
   }
   
   // read byte 0

   cas->section_syntax_indicator = bs_read_u1(b); 
   if (!cas->section_syntax_indicator) 
   {
      LOG_ERROR("section_syntax_indicator not set in CAT"); 
      reportAddErrorLog("section_syntax_indicator not set in CAT"); 
      SAFE_REPORT_TS_ERR(-31); 
      resetPSITableBuffer(catBuffer);
      bs_free (b);
      return 0;
   }
   bs_skip_u(b, 3); // TODO read the zero bit, check it to be zero
   cas->section_length = bs_read_u(b, 12); 
   if (cas->section_length > 1021) // max CAT length 
   {
      LOG_ERROR_ARGS("CAT section length is 0x%02X, larger than maximum allowed 0x%02X", 
                     cas->section_length, MAX_SECTION_LEN); 
      reportAddErrorLogArgs("CAT section length is 0x%02X, larger than maximum allowed 0x%02X", 
                     cas->section_length, MAX_SECTION_LEN); 
      SAFE_REPORT_TS_ERR(-32); 
      resetPSITableBuffer(catBuffer);
      bs_free (b);
      return 0;
   }
   
   if (cas->section_length > bs_bytes_left(b))
   {
      LOG_DEBUG ("conditional_access_section_read: Detected section spans more than one TS packet -- allocating buffer");

      if (catBuffer->buffer != NULL)
      {
         // should never get here
         LOG_ERROR ("conditional_access_section_read: unexpected catBufffer");
         reportAddErrorLog ("conditional_access_section_read: unexpected catBufffer");
         resetPSITableBuffer(catBuffer);
      }

      catBuffer->bufferAllocSz = cas->section_length + 3;
      catBuffer->buffer = (uint8_t *)calloc (cas->section_length + 3, 1);
      memcpy (catBuffer->buffer, buf, buf_len);
      catBuffer->bufferUsedSz = buf_len;

      bs_free (b);
      return 0;
   }

   // read bytes 1-2
   bs_read_u16(b); 
   
   // read bytes 3,4
   bs_skip_u(b, 2); 
   cas->version_number = bs_read_u(b, 5); 
   cas->current_next_indicator = bs_read_u1(b); 
   if (!cas->current_next_indicator) LOG_WARN("This CAT is not yet applicable/n"); 
   
   // read byte 5
   
   cas->section_number = bs_read_u8(b); 
   cas->last_section_number = bs_read_u8(b); 
   if (cas->section_number != 0 || cas->last_section_number != 0) LOG_WARN("Multi-section CAT is not supported yet/n"); 
   
   // read bytes 6,7
   read_descriptor_loop(cas->descriptors, b, cas->section_length - 5 - 4 ); 

   // explanation: section_length gives us the length from the end of section_length
   // we used 5 bytes for the mandatory section fields, and will use another 4 bytes for CRC
   // the remaining bytes contain descriptors, most probably only one
   // again, it's much shorter in C :-)
   

   cas->CRC_32 = bs_read_u32(b); 
   
   // check CRC
   crc_t cas_crc = crc_init(); 
   cas_crc = crc_update(cas_crc, buf, bs_pos(b) - 4); 
   cas_crc = crc_finalize(cas_crc); 
   if (cas_crc != cas->CRC_32) 
   {
      LOG_ERROR_ARGS("CAT CRC_32 specified as 0x%08X, but calculated as 0x%08X", cas->CRC_32, cas_crc); 
      reportAddErrorLogArgs("CAT CRC_32 specified as 0x%08X, but calculated as 0x%08X", cas->CRC_32, cas_crc); 
      SAFE_REPORT_TS_ERR(-33); 
      resetPSITableBuffer(catBuffer);
      bs_free (b);
      return 0;
   } 

   
   bs_free(b); 
   resetPSITableBuffer(catBuffer);
   return 1;
}
		static void destroy(FileAction* action)
		{
			bs_free(action);
		}