What is the DirectShow filter can connect to H.264(raw format) output pin? - directshow

I am writing a File Source filter which has an Video output PIN, the output pin type is H.264 raw format:
HRESULT CVideoOutPin::GetMediaType(CMediaType *pMediaType)
{
CAutoLock lock(m_pFilter->pStateLock());
ZeroMemory(pMediaType, sizeof(CMediaType));
pMediaType->InitMediaType();
// {7807c3af-524f-11ce-9f53-0020af0ba770}
pMediaType->SetSubtype(&MEDIASUBTYPE_h264raw);
unsigned int * pSize = (unsigned int *) pMediaType->ReallocFormatBuffer(sizeof(unsigned int) * 2);
pSize[0] = m_pFlvFile->GetWidth();
pSize[1] = m_pFlvFile->GetHeight();
pMediaType->SetFormat((BYTE *)pSize, sizeof(unsigned int) * 2);
//*pMediaType = m_oVideoMediaType;
return S_OK;
}
I tried several decompress filter in GraphEdit.exe, and none of them can connect to my output pin.
Is there any DirectShow Filter I can use to complete the graph?

MEDIASUBTYPE_h264raw doesn't look like a standard media subtype. You should use MEDIASUBTYPE_AVC1 (no start codes) or MEDIASUBTYPE_H264 (with start codes) instead; see H.264 Media Types. If you use either of those subtypes, a suitable H.264 decoder should be able to connect to your output pin. Windows 7 comes with such an H.264 decoder, and third-party decoders should supply an appropriate input filter.

Related

How to use VSPI on ESP32 with Adafruit_SPIFlash

I'm trying to use VSPI port of ESP32-WROVER with "Adafruit_SPIFlash.h" library https://github.com/adafruit/Adafruit_SPIFlash
This question is similar to How to use SPI with ESP32 and Arduino , but I'm using "Adafruit_SPIFlash.h" library.
This library seems to be using ESP32-WROVER "internal" SPI port, where WROVER SPI FLASH chip is connected, as a default. I have another SPI FLASH chip connected to VSPI port which I'm trying to use to store some sensor data.
I tried changing CUSTOM_SPI statement, but code doesn't compile
#define CUSTOM_SPI SPI //tried changing SPI to: VSPI, &VSPI, SPI1, SPI2, &SPI2
I asked this from Adafruit forum and got answer: "Create a Adafruit_FlashTransport_SPI object for the secondary SPI interface, then feed that to the Adafruit_SPIFlash object when you create it." Unfortunately I'm so nooby on FW things that this didn't help me and my follow up question is not answered.
For example how would I need to modify sketch below to use VSPI?
// The MIT License (MIT)
// Copyright (c) 2019 Ha Thach for Adafruit Industries
#include "SdFat.h"
#include "Adafruit_SPIFlash.h"
// Uncomment to run example with custom SPI and SS e.g with FRAM breakout
// #define CUSTOM_CS A5
// #define CUSTOM_SPI SPI
#if defined(CUSTOM_CS) && defined(CUSTOM_SPI)
Adafruit_FlashTransport_SPI flashTransport(CUSTOM_CS, CUSTOM_SPI);
#elif defined(ARDUINO_ARCH_ESP32)
// ESP32 use same flash device that store code.
// SPIFlash can use partition table to detect fatfs partition
// Therefore there is no need to specify the SPI and SS
Adafruit_FlashTransport_ESP32 flashTransport;
#elif defined(ARDUINO_ARCH_RP2040)
// RP2040 use same flash device that store code.
// Therefore there is no need to specify the SPI and SS
// Use default (no-args) constructor to be compatible with CircuitPython partition scheme
Adafruit_FlashTransport_RP2040 flashTransport;
// For generic usage: Adafruit_FlashTransport_RP2040(start_address, size)
// If start_address and size are both 0, value that match filesystem setting in
// 'Tools->Flash Size' menu selection will be used
#else
// On-board external flash (QSPI or SPI) macros should already
// defined in your board variant if supported
// - EXTERNAL_FLASH_USE_QSPI
// - EXTERNAL_FLASH_USE_CS/EXTERNAL_FLASH_USE_SPI
#if defined(EXTERNAL_FLASH_USE_QSPI)
Adafruit_FlashTransport_QSPI flashTransport;
#elif defined(EXTERNAL_FLASH_USE_SPI)
Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, EXTERNAL_FLASH_USE_SPI);
#else
#error No QSPI/SPI flash are defined on your board variant.h !
#endif
#endif
Adafruit_SPIFlash flash(&flashTransport);
/* If you want to use a specific flash device, for example for a custom built board, first look for it in Adafruit_SPIFlash\src\flash_devices.h
* If it isn't in there you need to create your own definition like the W25Q80DLX_EXAMPLE example below.
* These definitions need to be edited to match information on the data sheet of the flash device that you want to use.
* If you are not sure what the manufacture ID, memory type and capacity values should be, try running the sketch anyway and look at the serial output
* The flash device will report these values to you as a single hexadecimal value (the JDEC ID)
* For example, the first device on the list - the W25Q80DLX - will report its JDEC ID as 0xef4014, which is made of these three values:
* manufacturer_id = 0xef
* memory_type = 0x40
* capacity = 0x14
* With this macro properly defined you can then create an array of device definitions as shown below, this can include any from the list of devices in flash_devices.h, and any you define yourself here
* You need to update the variable on line 71 to reflect the number of items in the array
* You also need to uncomment line 84 and comment out line 81 so this array will be passed to the flash memory driver.
*
* Example of a user defined flash memory device:
#define W25Q80DLX_EXAMPLE \
{ \
.total_size = 1*1024*1024, \
.start_up_time_us = 5000, .manufacturer_id = 0xef, \
.memory_type = 0x40, .capacity = 0x14, .max_clock_speed_mhz = 80, \
.quad_enable_bit_mask = 0x02, .has_sector_protection = false, \
.supports_fast_read = true, .supports_qspi = true, \
.supports_qspi_writes = false, .write_status_register_split = false, \
.single_status_byte = false, .is_fram = false, \
}
*/
/*
* Create an array of data structures and fill it with the settings we defined above.
* We are using two devices, but more can be added if you want.
*/
//static const SPIFlash_Device_t my_flash_devices[] = {
// W25Q80DLX_EXAMPLE,
//};
/*
* Specify the number of different devices that are listed in the array we just created. If you add more devices to the array, update this value to match.
*/
//const int flashDevices = 1;
// the setup function runs once when you press reset or power the board
void setup()
{
Serial.begin(115200);
while ( !Serial ) delay(100); // wait for native usb
Serial.println("Adafruit Serial Flash Info example");
flash.begin();
//Using a flash device not already listed? Start the flash memory by passing it the array of device settings defined above, and the number of elements in the array.
//flash.begin(my_flash_devices, flashDevices);
Serial.print("JEDEC ID: 0x"); Serial.println(flash.getJEDECID(), HEX);
Serial.print("Flash size: "); Serial.print(flash.size() / 1024); Serial.println(" KB");
}
void loop()
{
// nothing to do
}

Type casting operation

I am using NodeMCU & Energy meter. Energy meter is Modbus RTU device which display parameter in 32 bit. With below piece of code I could able to read the data from slave but need method to type cast from into 32 bit floating & display
When I change the value to unsigned decimal in ModScan software the values showing properly. But I need to display value in 32 bit floating point.
#include <ModbusMaster232.h>
#include <SoftwareSerial.h>
float data[100];
ModbusMaster232 node(1);
// Define one address for reading
#define address 1
// Define the number of bits to read
#define bitQty 70
void setup()
{
Serial.begin(9600);
// Initialize Modbus communication baud rate
node.begin(9600);
}
void loop()
{
int result = node.readHoldingRegisters(address, bitQty);
data[0] = (float)node.getResponseBuffer(0);
data[1] = (float)node.getResponseBuffer(1);
data[2] = (float)node.getResponseBuffer(2);
data[3] = (float)node.getResponseBuffer(3);
data[4] = (float)node.getResponseBuffer(4);
data[5] = (float)node.getResponseBuffer(5);
for (int i = 0; i < 100; i++)
{
//data[i] = node.getResponseBuffer(i);
Serial.println(data[i]);
}
Serial.println("............");
}
I would like to display the reading as shown in Modbus with type casting.
Actual Modbus device output from salve:
Arduino output while read data from energy meter:
You are casting a 16-bit word into a float. Check the slave documentation to find how they map a 32-bit floating point into two Modbus registers. Basically you need to know where the least significant word is (first or second register), load them into memory (shift if necessary) and cast to float.
I am looking and trying to solve exact same problem (with same results). This may help:
function read() {
client.readHoldingRegisters(0000, 12)
.then(function(d) {
var floatA = d.buffer.readFloatBE(0);
console.log("Total kWh: ", floatA); })
.catch(function(e) {
console.log(e.message); })
.then(close);
}
This is NodeJS and javascript version, which works and Arduino does not. Complete example can be found here and it works on Raspberry Pi https://github.com/yaacov/node-modbus-serial/blob/master/examples/buffer.js

zigbee module callback function incompatible to ZCL spec

I have followed the ZCL report to implement the function which is able to receive the data sent from the sensor.
In the SDk, it is defined as the following:
void ZbZclReportFunc{
struct ZbZclClusterT * clusterPtr,
zbApsdeDataInt * dataIndPtr,
uint16_t attributeId,
const uint8_t * data
}
By implementing the callback function as shown above, I am able to receive all information except data.
In ZCL spec, the Temperature Measurement Cluster defines its "MeasuredValue" Signed 16-bit Integer.
I print out the data using the following format:
printf("Degree: 0x%04x", *data);
As I expect, the data shown is "0x002b" as an example.
By casting it to Signed 16-bit integer, it does not help.
printf("Degree: 0x%04x", (int16_t)*data);
Any idea?
Thanks
Zigbee packet data is little Endian. Also, the units for MeasuredValue are "hundredths of degrees Celsius". So if your measured temperature value was 26 degrees celsius, your data buffer would look like: 28 0A. To convert to celsius you would use:
double temperature = (double)((int16_t)(data[1] << 8) | (int16_t)data[0]) / 100.0;

Onewire temperatures to MQTT broker server

I am trying to modify the code from the example included in the onewire library for arduino so that no matter how many onewire devices I have plugged it will always find them and publish it to a MQTT using the device ID and the current temperature. I have gotten it to publish the temperature, but am having trouble adding the device ID or ROM which is in HEX to my topic.
So for example i want it to appear like this. Note the topic and msg for MQTT need to be Char* (more info here: http://knolleary.net/arduino-client-for-mqtt/api/#publish1)
topic = Celsius eg 12.09
payload (or msg) = \home[ROM]\temperature\current eg. \home\2894AA6220025\temperature\current
(just an example of the output you normally get when you run the code without my additions, this is the serial output!! notice the ROM and celsius that I want to use)
Have put my full code here, it is just a modification of the included onewire example with the pubsub MQTT part added on.
(see line 155 onwards) https://gist.github.com/matbor/5931466
//publish the temp now to mqtt topic
String strTopic = "/house/285A9282300F1/temperature/current"; // need to replace the 285A9282300F1 with the ROM ID on each LOOP!
char charMsg[10];
String strMsg = dtostrf(celsius, 4, 2, charMsg); //convert celsius to char
char charTopic[strTopic.length() + 1];
//char charMsg[strMsg.length() + 1];
strTopic.toCharArray(charTopic, sizeof(charTopic));
strMsg.toCharArray(charMsg, sizeof(charMsg));
client.publish(charTopic,charMsg);
Add this to the top of your sketch, outside of the loop function:
char hexChars[] = "0123456789ABCDEF";
#define HEX_MSB(v) hexChars[(v & 0xf0) >> 4]
#define HEX_LSB(v) hexChars[v & 0x0f]
This defines a pair of macros that return the most-significant and least-significant bytes of an int as the appropriate HEX character. (There may be more appropriate built-in's for this, but this is what I use out of habit).
The following code will insert the ROM, as a HEX string, into the topic. Note you can create the topic as a char[] directly - you don't need to go via a String object.
char charTopic[] = "/house/XXXXXXXXXXXXXXXX/temperature/current";
for (i = 0; i < 8; i++) {
charTopic[7+i*2] = HEX_MSB(addr[i]);
charTopic[8+i*2] = HEX_LSB(addr[i]);
}
For the payload, I'm not sure if it is 100% necessary, but I always explicitly initialise any char[] to all 0's when using as a buffer. This ensures whatever is written into the buffer will definitely be null-terminated. Again, you don't need to go via String types:
char charMsg[10];
memset(charMsg,'\0',10);
dtostrf(celsius, 4, 2, charMsg);
Finally, publish the message:
client.publish(charTopic,charMsg);

how to print a uint16 monochrome image in Qt?

I'm trying to print a image from a Dicom file. I pass the raw data to a convertToFormat_RGB888 function. As far as I know, Qt can't handle monochrome 16 bits images.
Here's the original image (converted to jpg here):
http://imageshack.us/photo/my-images/839/16bitc.jpg/
bool convertToFormat_RGB888(gdcm::Image const & gimage, char *buffer, QImage* &imageQt)
Inside this function, I get inside this...
...
else if (gimage.GetPixelFormat() == gdcm::PixelFormat::UINT16)
{
short *buffer16 = (short*)buffer;
unsigned char *ubuffer = new unsigned char[dimX*dimY*3];
unsigned char *pubuffer = ubuffer;
for (unsigned int i = 0; i < dimX*dimY; i++)
{
*pubuffer++ = *buffer16;
*pubuffer++ = *buffer16;
*pubuffer++ = *buffer16;
buffer16++;
}
imageQt = new QImage(ubuffer, dimX, dimY, QImage::Format_RGB888);
...
This code is a little adaptation from here:
gdcm.sourceforge.net/2.0/html/ConvertToQImage_8cxx-example.html
But the original one I got a execution error. Using mine at least I get an image, but it's not the same.
Here is the new image (converted to jpg here):
http://imageshack.us/photo/my-images/204/8bitz.jpg/
What am I doing wrong?
Thanks.
Try to get values of pixels from buffer manually and pass it to QImage::setPixel. It can be simplier.
You are assigning 16-bit integer to 8-bit variables here:
*pubuffer++ = *buffer16;
The result is undefined and most compilers just move the lower 8 bits to the destination. You want the upper 8 bits
*pubuffer++ = (*buffer16) >> 8;
The other issue is endianness. Depending to the endianness of the source data, you may need to call one of the QtEndian functions.
Lastly, you don't really need to use any of the 32 or 24-bit Qt image formats. Use 8-bit QImage::Format_Indexed8 and set the color table to grays.

Resources