I want to play local video file in Qt platform using ffmpeg to decode.Everything is OK except that play speed is as twice as normal.
The first thing I think about is that there must be a sampling frequency involved.But to be a new to ffmpeg,I don't know how to fix this problem.
Above is my code to read frame,is anyone can tell me what's wrong with the code ?
void VideoThread::run()
{
m_pInFmtCtx = avformat_alloc_context(); //ini struct
char path[] = "d:/test.mp4";
// open specific file
if(avformat_open_input(&m_pInFmtCtx, *path, NULL, NULL)){
{
qDebug()<<"get rtsp failed";
return;
}
else
{
qDebug()<<"get rtsp success";
}
if(avformat_find_stream_info(m_pInFmtCtx, NULL) < 0)
{
qDebug()<<"could not find stream information";
return;
}
int nVideoIndex = -1;
for(int i = 0; i < m_pInFmtCtx->nb_streams; i++)
{
if(m_pInFmtCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
nVideoIndex = i;
break;
}
}
if(nVideoIndex == -1)
{
qDebug()<<"could not find video stream";
return;
}
qDebug("---------------- File Information ---------------");
m_pCodecCtx = m_pInFmtCtx->streams[nVideoIndex]->codec;
m_pCodec = avcodec_find_decoder(m_pCodecCtx->codec_id);
if(!m_pCodec)
{
qDebug()<<"could not find codec";
return;
}
//start Decoder
if (avcodec_open2(m_pCodecCtx, m_pCodec, NULL) < 0) {
qDebug("Could not open codec.\n");
return;
}
//malloc space for stroring frame
m_pFrame = av_frame_alloc();
m_pFrameRGB = av_frame_alloc();
m_pOutBuf = (uint8_t*)av_malloc(avpicture_get_size(AV_PIX_FMT_RGB32, m_pCodecCtx->width, m_pCodecCtx->height));
avpicture_fill((AVPicture*)m_pFrameRGB, m_pOutBuf, AV_PIX_FMT_RGB32, m_pCodecCtx->width, m_pCodecCtx->height);
//for color switch,from YUV to RGB
struct SwsContext *pImgCtx = sws_getContext(m_pCodecCtx->width, m_pCodecCtx->height, m_pCodecCtx->pix_fmt,
m_pCodecCtx->width, m_pCodecCtx->height, AV_PIX_FMT_RGB32, SWS_BICUBIC, NULL, NULL, NULL);
int nSize = m_pCodecCtx->width * m_pCodecCtx->height;
m_pPacket = (AVPacket *)av_malloc(sizeof(AVPacket));
if(av_new_packet(m_pPacket, nSize) != 0)
{
qDebug()<<"new packet failed";
}
//isInterruptionRequested is a flag,determine whether the thread is over
// read each frame from specific video file
while (!isInterruptionRequested())
{
int nGotPic = 0;
if(av_read_frame(m_pInFmtCtx, m_pPacket) >= 0)
{
if(m_pPacket->stream_index == nVideoIndex)
{
//avcodec_decode_video2()transform from packet to frame
if(avcodec_decode_video2(m_pCodecCtx, m_pFrame, &nGotPic, m_pPacket) < 0)
{
qDebug()<<"decode failed";
return;
}
if(nGotPic)
{ // transform to RGB color
sws_scale(pImgCtx, (const uint8_t* const*)m_pFrame->data,
m_pFrame->linesize, 0, m_pCodecCtx->height, m_pFrameRGB->data,
m_pFrameRGB->linesize);
// save to QImage,for later use
QImage *pImage = new QImage((uchar*)m_pOutBuf, m_pCodecCtx->width, m_pCodecCtx->height, QImage::Format_RGB32);
}
}
}
av_free_packet(m_pPacket);
msleep(5);
}
exec();
}
Related
I have a menu function, in which I input a question and two options, then the user choses one. It works just fine everytime but one ; I call
if (menu("ou est le corps?","interieur ","exterieur")==1)
{
but instead of printing "interieur " It shows "p?"
it works just fine without the space, but I need to make a space and \n does quite the same thing.
I have another call of this function, with \n which works fine so I have no idea about why this wouldn't work. Anyone has got an idea?
PS : the value of choix1 is then sent via bluetooth, and there it stays intact.
PPS : tell me if something is unclear, I'm not naturally english
PPPS(sorry) : tried to run the same code again, it seems to print a random character followed by "?", I had twice "p?", once "?" and once " '?"
[updates] once "#?"
int menu (String texte, String choix1, String choix2)
{
envoye = 0;
rxValue = "0";
while (digitalRead(M5_BUTTON_HOME) != LOW && rxValue == "0")
{
heure();
M5.Lcd.setTextSize(2);
M5.Lcd.print(texte);
M5.Lcd.printf("\n");
if (selec == 0)
{
M5.Lcd.printf("->%s %s", choix1, choix2);
}
else
{
M5.Lcd.printf(" %s ->%s", choix1, choix2);
}
if (M5.BtnB.read() != 0)
{
if (selec == 0)
{
selec = 1;
}
else
{
selec = 0;
}
while (M5.BtnB.read() != 0)
{
if(digitalRead(M5_BUTTON_HOME) == LOW)
{
M5.Lcd.fillScreen(BLACK);
delay(1000);
if(digitalRead(M5_BUTTON_HOME) == LOW)
{
choix=50;
heure();
delay(1000);
return 1;
}
}
}
}
if (deviceConnected && envoye == 0)
{
sendchoix(texte, choix1, choix2);
envoye++;
}
}
if (rxValue != "0")
{
recuble = &rxValue[0];
selec = atoi(recuble) - 1;
rxValue = "0";
}
M5.Lcd.fillScreen(BLACK);
delay(300);
return selec;
}
int menu (String texte, String choix1, String choix2) {
[...]
M5.Lcd.printf("->%s %s", choix1, choix2);
You cannot treat String objects as const char*, which is what the format specifier %s is expecting. String is an Arduino class for storing.. strings/character data, but an object of this class is not equivalent to the raw pointer to the data.
For that, you need to call the c_str() method on the String object to get the C-String pointer to the data, as shown in the documentation [1].
[..]
M5.Lcd.printf("->%s %s", choix1.c_str(), choix2.c_str());
[..]
[1] https://www.arduino.cc/reference/en/language/variables/data-types/string/functions/c_str/
Having a problem regarding the use of IAMStreamConfig interface.
I have the following code to set the output format:
private void SetFormat(IAMStreamConfig streamConfig, VideoCapabilities resolution = null)
{
int capabilitiesCount = 0, capabilitySize = 0;
AMMediaType newMediaType = null;
var caps = new VideoStreamConfigCaps();
streamConfig.GetNumberOfCapabilities(out capabilitiesCount, out capabilitySize);
for (int i = 0; i < capabilitiesCount; i++)
{
try
{
var vc = new VideoCapabilities(streamConfig, i);
if (resolution == vc || resolution == null)
{
if (streamConfig.GetStreamCaps(i, out newMediaType, caps) == 0)
break;
}
}
catch { }
}
if (newMediaType != null)
{
if (averageTimePerFrame >= 0)
{
unsafe
{
VideoInfoHeader* vih = (VideoInfoHeader*)newMediaType.FormatPtr;
vih->AverageTimePerFrame = averageTimePerFrame;
}
}
streamConfig.SetFormat(newMediaType);
newMediaType.Dispose();
newMediaType = null;
}
}
Till yesterday I never had any problem with any device, but yesterday I tested this with a new video source, Osprey 850e SDI, and I always get a blue screen when trying to set the format:
streamConfig.SetFormat(newMediaType)
The format being set is YUY2.
Anyone ever came across a similar issue or has any suggestions?
Thank you.
EDIT:
These are the details of the media type supplied:
Major Type: 73646976-0000-0010-8000-00aa00389b71 WMMEDIATYPE_Video
Sub Type: 59565955-0000-0010-8000-00aa00389b71 MEDIASUBTYPE_UYVY
Fixed Size Samples: true
Temporal Compression: false
Sample Size 691200
Format Type: 05589f80-c356-11ce-bf01-00aa0055595a WMFORMAT_VideoInfo
unkPtr: 0
Format Size: 88
FormatPtr: 111386040
I'm using an STM32F405OG for a project and one of the necessary functions is monitoring 3 analog channels at ~1 Hz. My desired implementation is starting an ADC DMA read of all 3 channels in Scan mode and retrieving the results at a later time after the DMA complete interrupt has occurred.
I'm using ADC1 and have tried both DMA channels 0 and 4, both with the same result: HAL_ADC_ErrorCallback() is invoked after the first call to HAL_ADC_Start_DMA(). At this point, the ADC handle is in an error state (HAL_ADC_STATE_ERROR_DMA) with the error code 0x04 (HAL_ADC_ERROR_DMA). Checking the linked DMA handle yields a DMA error code of HAL_DMA_ERROR_NO_XFER, meaning "Abort requested with no Xfer ongoing."
I'm totally lost as to what's causing this - my code should be consistent with examples and the "how to use this module" comments at the top of stm32f4xx_hal_adc.c. I've attached my code below.
ADC_HandleTypeDef ADC_hADC =
{
.Instance = ADC1,
.Init =
{
.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV8,
.Resolution = ADC_RESOLUTION_12B,
.EOCSelection = ADC_EOC_SEQ_CONV, // EOC at end of sequence of channel conversions
.ScanConvMode = ENABLE,
.ContinuousConvMode = DISABLE,
.DiscontinuousConvMode = DISABLE,
.NbrOfDiscConversion = 0U,
.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE,
.ExternalTrigConv = ADC_SOFTWARE_START,
.DataAlign = ADC_DATAALIGN_RIGHT,
.NbrOfConversion = _NUM_ADC_CONV,
.DMAContinuousRequests = DISABLE
}
};
DMA_HandleTypeDef _hDmaAdc =
{
.Instance = DMA2_Stream0,
.Init =
{
.Channel = DMA_CHANNEL_0,
.Direction = DMA_PERIPH_TO_MEMORY,
.PeriphInc = DMA_PINC_DISABLE,
.MemInc = DMA_MINC_ENABLE,
.PeriphDataAlignment = DMA_PDATAALIGN_WORD,
.MemDataAlignment = DMA_MDATAALIGN_WORD,
.Mode = DMA_NORMAL,
.Priority = DMA_PRIORITY_HIGH,
.FIFOMode = DMA_FIFOMODE_DISABLE,
.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL,
.MemBurst = DMA_MBURST_SINGLE,
.PeriphBurst = DMA_PBURST_SINGLE
}
};
void HAL_ADC_MspInit(ADC_HandleTypeDef *h)
{
if (!h)
{
return;
}
else if (h->Instance == ADC1)
{
__HAL_RCC_ADC1_CLK_ENABLE();
__HAL_RCC_DMA2_CLK_ENABLE();
HAL_DMA_Init(&_hDmaAdc);
__HAL_LINKDMA(h, DMA_Handle, _hDmaAdc);
HAL_NVIC_SetPriority(ADC_IRQn, IT_PRIO_ADC, 0);
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, IT_PRIO_ADC, 0);
HAL_NVIC_EnableIRQ(ADC_IRQn);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
}
}
uint32_t _meas[3];
ADC_ChannelConfTypeDef _chanCfg[3] =
{
// VIN_MON
{
.Channel = ADC_CHANNEL_1,
},
// VDD_MON
{
.Channel = ADC_CHANNEL_8,
},
// VDD2_MON
{
.Channel = ADC_CHANNEL_2,
}
};
Bool ADC_Init(void)
{
ADC_DeInit();
memset(_meas, 0, sizeof(_meas));
Bool status = (HAL_ADC_Init(&ADC_hADC) == HAL_OK);
if (status)
{
// Configure each ADC channel
for (uint32_t i = 0U; i < NELEM(_chanCfg); i++)
{
_chanCfg[i].Rank = (i + 1U);
_chanCfg[i].SamplingTime = ADC_SAMPLETIME_480CYCLES;
_chanCfg[i].Offset = 0U;
if (HAL_ADC_ConfigChannel(&ADC_hADC, &_chanCfg[i]) != HAL_OK)
{
status = FALSE;
break;
}
}
_state = ADC_STATE_READY;
}
if (!status)
{
ADC_DeInit();
}
return status;
}
Bool ADC_StartRead(void)
{
Bool status = TRUE;
status = (HAL_ADC_Start_DMA(&ADC_hADC, &_meas[0], 3) == HAL_OK);
return status;
}
After slowing down the conversions via the ClockPrescaler init structure field, increasing the number of ADC cycles, and calling HAL_ADC_Stop_DMA() (per file header comment in stm32f4xx_hal_adc.c), everything is working.
Note that calling HAL_ADC_Stop_DMA() in the DMA Transfer Complete ISR caused the aforementioned error conditions as well, so calls to that function will have to be made sometime after the DMAXferCplt ISR is invoked.
I want to adjust the brightness of my monitor on Windows.
I follow this page:
How to use GetMonitorCapabilities and GetMonitorBrightness functions
but, the GetMonitorCapabilities function returns false.
I printed using qDebug, hPhysicalMonitor is NULL. Is this point wrong?
(The GetPhysicalMonitorsFromHMONITOR function returns true)
How can I fix this code?
HMONITOR hMonitor = NULL;
DWORD cPhysicalMonitors = 1;
LPPHYSICAL_MONITOR pPhysicalMonitors;
HWND hWnd = GetDesktopWindow();
// Get the monitor handle.
hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTOPRIMARY);
// Get the number of physical monitors.
BOOL bSuccess = GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor, &cPhysicalMonitors);
if (bSuccess)
{
// Allocate the array of PHYSICAL_MONITOR structures.
pPhysicalMonitors = (LPPHYSICAL_MONITOR)malloc(cPhysicalMonitors* sizeof(PHYSICAL_MONITOR));
if (pPhysicalMonitors != NULL)
{
// Get the array.
bSuccess = GetPhysicalMonitorsFromHMONITOR( hMonitor, cPhysicalMonitors, pPhysicalMonitors);
if (bSuccess == FALSE)
{
qDebug("GetPhysicalMonitorsFromHMONITOR");
}
// Get physical monitor handle.
HANDLE hPhysicalMonitor = pPhysicalMonitors[0].hPhysicalMonitor;
DWORD pdwMonitorCapabilities = 0;
DWORD pdwSupportedColorTemperatures = 0;
bSuccess = GetMonitorCapabilities(hPhysicalMonitor, &pdwMonitorCapabilities, &pdwSupportedColorTemperatures);
if (bSuccess == FALSE)
{
qDebug("GetMonitorCapabilities");
}
DWORD pdwMinimumBrightness = 0;
DWORD pdwCurrentBrightness = 0;
DWORD pdwMaximumBrightness = 0;
bSuccess = GetMonitorBrightness(hPhysicalMonitor, &pdwMinimumBrightness, &pdwCurrentBrightness, &pdwMaximumBrightness);
if (bSuccess == FALSE)
{
qDebug("GetMonitorBrightness");
}
qDebug(QByteArray::number(bSuccess));
qDebug(QByteArray::number((WORD)pdwMinimumBrightness));
qDebug(QByteArray::number((WORD)pdwCurrentBrightness));
qDebug(QByteArray::number((WORD)pdwMaximumBrightness));
// Close the monitor handles.
bSuccess = DestroyPhysicalMonitors(cPhysicalMonitors, pPhysicalMonitors);
// Free the array.
free(pPhysicalMonitors);
}
}
If you want to adjust the brightness using WmiMonitorBrightnessMethods use the code below.
public static void SetWmiMonitorBrightness(byte targetBrightness)
{
ManagementScope scope = new ManagementScope("root\\WMI");
SelectQuery query = new SelectQuery("WmiMonitorBrightnessMethods");
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query))
{
using (ManagementObjectCollection objectCollection = searcher.Get())
{
foreach (ManagementObject mObj in objectCollection)
{
mObj.InvokeMethod("WmiSetBrightness",
new Object[] { UInt32.MaxValue, targetBrightness });
break;
}
}
}
}
Doing GetMonitorBrightness on the specific monitor I have causes ERROR_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA.
So I used WmiSetBrightness instead. It works fine.
If you got a tip related to ERROR_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA, please share it with me.
Now I have create an ogg decoder in media foundation.
I have decode the ogg data to PCM data in IMFTransform::ProcessOutput.
but I cannot play the PCM data, so now how to play the pcm data?
This is my ProcessOutput code:
HRESULT OggDecoder:: ProcessOutput(
DWORD dwFlags, DWORD cOutputBufferCount,
MFT_OUTPUT_DATA_BUFFER *pOutputSamples, // one per stream
DWORD *pdwStatus )
{
if (dwFlags != 0)
{
return E_INVALIDARG;
}
if (pOutputSamples == NULL || pdwStatus == NULL)
{
return E_POINTER;
}
// Must be exactly one output buffer.
if (cOutputBufferCount != 1)
{
return E_INVALIDARG;
}
// It must contain a sample.
if (pOutputSamples[0].pSample == NULL)
{
return E_INVALIDARG;
}
EnterCriticalSection(&m_critSec);
HRESULT hr = S_OK;
DWORD cbData = 0;
IMFMediaBuffer *pOutput = NULL;
// If we don't have an input sample, we need some input before
// we can generate any output.
if (!HasPendingOutput())
{
hr = MF_E_TRANSFORM_NEED_MORE_INPUT;
}
// Get the output buffer.
if (SUCCEEDED(hr))
{
hr = pOutputSamples[0].pSample->GetBufferByIndex(0, &pOutput);
}
if (SUCCEEDED(hr))
{
hr = pOutput->GetMaxLength(&cbData);
}
if (SUCCEEDED(hr))
{
BYTE* pPCM=NULL;
pOutputBuffer->Lock(&pPCM,NULL,NULL);
GetPCMData(&pPCM); // decode audio data here
pOutputBuffer->SetCurrentLength(nLength);
pOutputSamples[0].pSample->SetSampleTime(sampleTime);
pOutputSamples[0].pSample->SetSampleDuration(sampleDuration);
pOutputBuffer->Unlock();
}
SafeRelease(&pOutput);
LeaveCriticalSection(&m_critSec);
return hr;
}
Is there I missing something or what' wrong with this code.
thanks.
if you use topoedit.exe for debug, it can add one resampler DMO automatically which is a DMO for converting pcm to float format.
you can write the player app, and create the topology by youself, and then you add the resamplyer dmo node.