Effizienz Frage

Der Wolf

Erfahrenes Mitglied
Hallo,

ich versuche mich im Moment an einem gstreamer plugin um die Bild-Daten und andere errechnete Daten über eine bestimmte Middleware an andere Komponenten verschicken zu können. Dafür muss ich die guint8 Daten die gstreamer in einem Buffer verschickt in eine Ice::ByteSeq verpacken um sie dann verschicken zu können. Im Moment mache ich das über folgenden Code:

Code:
void
XcfExporter::processBuffer(GstBuffer *buffer) {

	gst_buffer_ref(buffer);

	XCF::Binary::TransportVecBytePtr transport = new XCF::Binary::TransportVecByte();
	std::vector<unsigned char> values(buffer->size);
	for (int i = 0; i < buffer->size; i++) {
		values[i] = (buffer->data)[i];
	}
	transport->set(values);

	XCF::CTUPtr ctu = new XCF::CTU();
	ctu->setXML("<MIXELGRAM></MIXELGRAM>");
	ctu->addBinary("image", transport);

	mixelgramPublisher->send(ctu);

	gst_buffer_unref(buffer);

}

Ich kann mir aber vorstellen, dass man das Kopieren der Daten bestimmt auch effizienter gestalten kann. Hat jemand da einen Vorschlag für mich?

Gruß
Der Wolf
 
Hi.

Initialisiere den Vektor doch direkt mit den Daten:
C++:
std::vector<unsigned char> values(buffer->data, buffer->data + buffer->size);
Dies sollte im Normalfall dazu führen dass memcpy verwendet wird, welches um Größenordnungen schneller sein dürfte als eine Schleife.

Vermutlich gibt es allerdings auch direkt einen ByteSeq Konstruktor welcher die Daten direkt aufnehmen kann, so dass man nicht noch einen temporären Vektor kreieren muss. Ich habe allerdings keine Doku gefunden...

Gruß
 
Hi,

gleich die nächste Frage ... wenn in dem data->buffer ein Array mit guint8 was wohl ein anderer Name für unsigned char ist steckt und wenn ich annehme, dass da ursprünglich int Werte drin standen die jetzt als unsigned char codiert sind, müsste ich die dann nicht über folgenden code wieder in einen vector mit unsigned int Werten konvertieren können?

C++:
void
AudioAnalyse::processData(GstBuffer *buffer) {

	gst_buffer_ref(buffer);

	std::cout << "Entering ... " << std::endl;

	std::string mimeType = getMimeType(buffer);
	std::cout << mimeType << std::endl;

	unsigned int *tmpData = (unsigned int*) buffer->data;	

	std::vector<unsigned int> values(tmpData, tmpData + (buffer->size / sizeof(unsigned int)));

	float average = 0;
	for (int i = 0; i < buffer->size; i++) {
		average = average + values[i];		
	}
	std::cout << "Average: " << (average /= values.size()) << " Size: " << values.size() << std::endl;
	
	gst_buffer_unref(buffer);
	
}

Ich bekomme allerdings teilweise errechnete average Werte raus die über dem liegen, was gstreamers alsasrc plugin angeblich rauswirft und ab und an bekomme ich auch einen SEGSEV Fehler. :(

Gruß
Der Wolf
 
Zuletzt bearbeitet:
Also den SIGSEV Fehler hab ich mittlerweile gefunden. Der lag darin begründet, dass meine Schleife einfach zu weit gelaufen ist, da ich über die Größe des Buffers und nicht des Vektors iteriere ... Zeile 17 muss also so lauten:

C++:
for (int i = 0; i < values.size(); i++) {

Und ich hab auch gesehen, dass die Werte die gstreamer mir liefert nicht unsigned sondern signed sind.
Trotzdem würde mich mal interessieren, ob der allgmeine Ansatz, dass ich so den Speicherbereich von byte nach int uminterpretieren kann, richtig ist, wie ich ihn hier angegangen bin.

Gruß
Der Wolf
 
Hi.
Trotzdem würde mich mal interessieren, ob der allgmeine Ansatz, dass ich so den Speicherbereich von byte nach int uminterpretieren kann, richtig ist, wie ich ihn hier angegangen bin.
Typen sind lediglich eine Hilfe des Compilers. Wenn du eine Byte-Sequenz übergeben bekommst, es aber besser weißt, da es sich dabei tatsächlich um eine Int-Sequenz handelt, dann ist es völlig OK zu casten.

Allerdings empfiehlt es sich in C++ die neuen Cast-Operatoren (reinterpret_cast etc.) zu verwenden.

Gruß
 
Zurück