I'm trying to use intel-media-sdk decoder for h.264 videos. Here is my code for initializing decoder :
mfxStatus decoder::initDecoder(HWND window, mfxBitstream *Header) {
mfxStatus sts = MFX_ERR_NONE;
mfxVersion ver = { { 0, 1 } };
mfxVideoParam mfxVideoParams;
mfxFrameAllocator mfxAllocator;
mfxFrameAllocResponse mfxResponse;
sts = m_mfxSession.Init(MFX_IMPL_AUTO_ANY, &ver); //sts = MFX_ERR_NONE
if (sts == MFX_ERR_NONE) {
sts = m_mfxSession.SetHandle(MFX_HANDLE_DIRECT3D_DEVICE_MANAGER9,
m_renderer.initD3d(GetIntelDeviceAdapterNum(), window)); //sts = MFX_ERR_NONE
if (sts == MFX_ERR_NONE) {
mfxAllocator.pthis = m_mfxSession;
sts = m_mfxSession.SetFrameAllocator(&mfxAllocator); //sts = MFX_ERR_NONE
if (sts == MFX_ERR_NONE) {
MFXVideoDECODE mfxDEC(m_mfxSession);
m_mfxVideoDecode = mfxDEC;
memset(&mfxVideoParams, 0, sizeof(mfxVideoParams));
mfxVideoParams.mfx.CodecId = MFX_CODEC_AVC;
mfxVideoParams.IOPattern = MFX_IOPATTERN_OUT_VIDEO_MEMORY;
sts = m_mfxVideoDecode.DecodeHeader(Header, &mfxVideoParams); //sts = MFX_ERR_NONE
if (sts == MFX_ERR_NONE) {
memset(&m_mfxRequest, 0, sizeof(m_mfxRequest));
sts = m_mfxVideoDecode.QueryIOSurf(&mfxVideoParams, &m_mfxRequest); //sts = MFX_ERR_NONE
if (sts == MFX_ERR_NONE) {
sts = m_renderer.allocSurfaces(mfxAllocator.pthis, &m_mfxRequest, &mfxResponse);
if (sts == MFX_ERR_NONE) {
m_pmfxSurfaces = new mfxFrameSurface1 *[m_mfxRequest.NumFrameSuggested];
for (int i = 0; i < m_mfxRequest.NumFrameSuggested; i++) {
m_pmfxSurfaces[i] = new mfxFrameSurface1;
memset(m_pmfxSurfaces[i], 0, sizeof(mfxFrameSurface1));
memcpy(&(m_pmfxSurfaces[i]->Info), &(mfxVideoParams.mfx.FrameInfo), sizeof(mfxFrameInfo));
// MID (memory id) represents one video NV12 surface
m_pmfxSurfaces[i]->Data.MemId = mfxResponse.mids[i];
};
sts = m_mfxVideoDecode.Init(&mfxVideoParams); //sts = MFX_ERR_MEMORY_ALLOC
}
}
}
}
}
}
return sts;
}
So as you can see MFXVideoDECODE::Init(mfxVideoParam*) (which internally calls MFXVideoDECODE_Init) returns MFX_ERR_MEMORY_ALLOC and the strange thing here is in this document it says this function does not have this return value.
Here is some debug information about mfxVideoParams :
AllocId = 0, AsyncDepth = 0, IOPattern = 16, mfx.CodecId = 541283905,
mfx.CodecProfile = 77, mfx.CodecLevel = 30, vpp.In.FourCC = 842094158,
vpp.In.Width = 864, vpp.In.Height = 480, vpp.In.CropW = 854,
vpp.In.CropH = 480, vpp.In.BufferSize = 31458144, vpp.In.AspectRatioW
= 1, vpp.In.AspectRatioH = 1, vpp.In.PicStruct = 1, vpp.In.ChromaFormat = 1
Here is Some member data definition in header which used here :
MFXVideoSession m_mfxSession;
MFXVideoDECODE m_mfxVideoDecode;
mfxFrameAllocRequest m_mfxRequest;
mfxFrameSurface1** m_pmfxSurfaces;
And Here is some information about my current working device that might relate to this problem:
Operating System : Windows 8.1
Processor : Intel(R) Core(TM) i5-3470 CPU # 3.20GHZ
System type : 64-bit operating system, x64-based processor
Installed memory (RAM) : 8.00 GB
And finally to reproduce the exact same situation I downloaded video named big_buck_bunny_1080p_h264.mov from this site and then extracted it with ffmpeg to h264 and used it in my program.
You need to initialize mfxFrameAlocator callback functions (Alloc, Free, GetHDL, ...) with proper functions.
for example :
//static member
mfxStatus decoder::gethdl(mfxHDL pthis, mfxMemId mid, mfxHDL* handle)
{
pthis; // To avoid warning for this unused parameter
if (handle == 0) return MFX_ERR_INVALID_HANDLE;
*handle = mid;
return MFX_ERR_NONE;
}
mfxStatus decoder::initDecoder(HWND window, mfxBitstream *Header) {
//blah blah
mfxAllocator.pthis = m_mfxSession;
mfxAllocator.GetHDL = gethdl;
//define for these too
//mfxAllocator.Alloc = alloc;
//mfxAllocator.Free = free;
//mfxAllocator.Lock = lock;
//mfxAllocator.Unlock = unlock;
//rest of your code
}
Related
1. About the problem
I'm trying to send data store in a array called UxbTx[64] to 2 Hid devices that have the same VendorID(VID) and ProductID(PID) but differ in SerialNum (this differnce help me to enumerate 2 devices) and connect to PC via Usb Hub . I have successfully recognized two device and use hid_write() to send data but just 1 device acting right with my data config. For example, i want to turn on 2 devices but device 1 ON whereas the device 2 still remain OFF.
2. What I have tried
At first I thought that I have failed to send to the second device but it not. I use res=hid_write() and it return 0 which means successfully send for both devices.
This is the code that i use:
static hid_device** id_device;
static int max_size;
int res;
struct device_info
{
wchar_t* serial_num;
int id;
};
std::vector<device_info> devEnum(unsigned short vendor_id, unsigned short product_id)
{
std::vector<device_info> device;
int count = 0, total = 0, res = 0,i=0;
hid_device_info* dev = NULL, * cur_dev = NULL;
hid_device* temp_handle = NULL;
std::vector<wchar_t*> string;
wchar_t wstr[MAX_STR], temp[MAX_STR];
device_info inf;
hid_enumerate(vendor_id, product_id);
res = hid_init();
dev = hid_enumerate(0x461, 0x20);
for (cur_dev = dev; cur_dev != NULL; cur_dev = cur_dev->next)
{
memcpy(temp, cur_dev->serial_number, MAX_STR);
wcsncpy(temp, cur_dev->serial_number, MAX_STR);
temp[MAX_STR - 1] = L'\0';
string.push_back(temp);
inf.serial_num = cur_dev->serial_number;
inf.id = count;
device.push_back(inf);
count++;
}
max_size = device.size();
return device;
}
int NhgIsOpen(wchar_t* Manufacturer, wchar_t* Product, wchar_t* SerialNumber, std::vector<device_info> devices) {
int length = devices.size();
int res = 0;
id_device = new hid_device * [length];
wchar_t KeyManufacturer[MAX_STR] = L"test";
wchar_t KeyProduct[MAX_STR] = L"device test";
for (int i = 0; i < length; i++)
{
id_device[i] = hid_open(0x123, 0x15, devices[i].serial_num);
if (!id_device[i])
return -2;
hid_set_nonblocking(id_device[i], 0);
res = hid_get_manufacturer_string(id_device[i], Manufacturer, MAX_STR);
if (wcscmp(Manufacturer, KeyManufacturer) != 0)
return -3; //Manufacturer not match
res = hid_get_product_string(id_device[i], Product, MAX_STR);
if (wcscmp(Product, KeyProduct) != 0)
return -4; // KeyProdeuct not match
}
return 0;
}
INT32 IoControl(UINT16 IoState, int axis_id) {
UINT8 UsbTx[64];
//clear TX buffer
std::fill_n(UsbTx, 64, 0);
//report byte
UsbTx[0] = 0x01;
//USB user define cmd
UsbTx[1] = 0x00;
UsbTx[2] = 0x15; // turn on device
UsbTx[11] = 0x00;
UsbTx[12] = (0xFF) & IoState;
res = hid_write(id_device[axis_id], UsbTx, 64);
if (res < 0)
return -5; //can't write
return 0;
}
3. Question
If i can enumerate 2 devices does it means i can talk to 2 devices simultaneously?
Does the Report ID in firmware is the problem? I mean does i have to re-config Report ID in the Descriptor of the device so they can read the data at the same time?
My preset:
m_stEncodeConfig.encodeCodecConfig.hevcConfig.sliceMode = 3u;
m_stEncodeConfig.encodeCodecConfig.hevcConfig.sliceModeData = (uint32_t)m_stEncodeStreamInfo.nMaxSliceNum; //4
m_stCreateEncodeParams.reportSliceOffsets = 1;
m_stCreateEncodeParams.enableSubFrameWrite = 1;
code of process output:
NV_ENC_LOCK_BITSTREAM lockBitstreamData;
memset(&lockBitstreamData, 0, sizeof(lockBitstreamData));
lockBitstreamData.version = NV_ENC_LOCK_BITSTREAM_VER;
lockBitstreamData.outputBitstream = pEncodeBuffer->stOutputBfr.hBitstreamBuffer;
lockBitstreamData.doNotWait = 1u;
std::vector<uint32_t> arrSliceOffset(m_stEncodeConfig.encodeCodecConfig.hevcConfig.sliceModeData);
lockBitstreamData.sliceOffsets = arrSliceOffset.data();
while (true)
{
NVENCSTATUS status = m_pEncodeAPI->nvEncLockBitstream(m_hEncoder, &lockBitstreamData);
auto tick = int(std::chrono::steady_clock::now().time_since_epoch().count() / 1000000);
if (status == NVENCSTATUS::NV_ENC_SUCCESS)
{
if (lockBitstreamData.hwEncodeStatus == 2)
{
static std::ofstream of("slice.h265", std::ios::trunc | std::ios::binary);
of.write((char*)lockBitstreamData.bitstreamBufferPtr, lockBitstreamData.bitstreamSizeInBytes);
of.flush();
break;
}
NVENCAPI_CALL_CHECK(m_pEncodeAPI->nvEncUnlockBitstream(m_hEncoder, lockBitstreamData.outputBitstream));
}
else
{
break;
}
}
play bitstream:
ffplay -i slice.h265
output : Packet corrupt
arrSliceOffset[0] always = 255.
I watch the memory from VS Debug and compare with enableSubFrameWrite = 0,the bitstreamSizeInBytes less of valid data size . It’s BUG or I loss some details? Anybady can tell me how can I correct use of enableSubFrameWrite
I'm trying to learn Vulkan by following the great tutorials from vulkan-tutorial.com but I'm having some trouble at the point where I must create the swap chain. As stated in the title, the vkCreateSwapchainKHR creates the following error: Access violation executing location 0x0000000000000000.
The tutorial suggest this might be a conflict with the steam overlay. This is not the case for me as copying the whole code from the tutorial works.
I'm trying to figure out what went wrong with my code and to learn how to debug such issues as I will not have a reference code in the future. The incriminated line looks this:
if (vkCreateSwapchainKHR(device, &swapChainCreateInfo, nullptr, &swapChain) != VK_SUCCESS) {
throw std::runtime_error("Could not create swap chain");
}
I setup a breakpoint at this line to compare the values of the arguments in my code with the values from the reference code. As far as I can tell, there is no difference. (The adresses of course are different)
Where should I look for a problem in my code? The variable swapChain is a NULL as expected. A wrongly formed swapChainCreateInfo should not make vkCreateSwapchainKHR crash. It would merely make it return something that is not VK_SUCCESS. And device was created without problem:
if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) {
throw std::runtime_error("Failed to create logical device");
}
EDIT - I am using the validation layer VK_LAYER_LUNARG_standard_validation and my createInfo setup is the following.
// Useful functions and structures
VkPhysicalDevice physicalDevice;
VkSurfaceKHR surface;
VkSwapchainKHR swapChain;
struct QueueFamilyIndices {
std::optional<uint32_t> graphicsFamily;
std::optional<uint32_t> presentationFamily;
bool isComplete() {
return graphicsFamily.has_value() && presentationFamily.has_value();
}
};
struct SwapChainSupportDetails {
VkSurfaceCapabilitiesKHR surfaceCapabilities;
std::vector<VkSurfaceFormatKHR> formats;
std::vector<VkPresentModeKHR> presentModes;
};
SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice physicalDevice) {
SwapChainSupportDetails swapChainSupportDetails;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &swapChainSupportDetails.surfaceCapabilities);
uint32_t formatCount = 0;
vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, nullptr);
if (formatCount != 0) {
swapChainSupportDetails.formats.resize(formatCount);
vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, swapChainSupportDetails.formats.data());
}
uint32_t presentModeCount = 0;
vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, nullptr);
if (presentModeCount != 0) {
swapChainSupportDetails.presentModes.resize(presentModeCount);
vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, swapChainSupportDetails.presentModes.data());
}
return swapChainSupportDetails;
}
VkSurfaceFormatKHR chooseSwapChainSurfaceFormat(const std::vector<VkSurfaceFormatKHR> & availableFormats) {
if (availableFormats.size() == 1 && availableFormats[0].format == VK_FORMAT_UNDEFINED) {
return { VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
}
for (const auto & availableFormat : availableFormats) {
if (availableFormat.format == VK_FORMAT_B8G8R8A8_UNORM && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
return availableFormat;
}
}
return availableFormats[0];
}
VkPresentModeKHR chooseSwapChainPresentMode(const std::vector<VkPresentModeKHR> & availablePresentModes) {
VkPresentModeKHR bestMode = VK_PRESENT_MODE_FIFO_KHR;
for (const auto & availablePresentMode : availablePresentModes) {
if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
return availablePresentMode;
}
else if (availablePresentMode == VK_PRESENT_MODE_IMMEDIATE_KHR) {
bestMode = availablePresentMode;
}
}
return bestMode;
}
VkExtent2D chooseSwapChainExtent2D(const VkSurfaceCapabilitiesKHR & surfaceCapabilities) {
if (surfaceCapabilities.currentExtent.width != std::numeric_limits<uint32_t>::max()) {
return surfaceCapabilities.currentExtent;
}
else {
VkExtent2D actualExtent = { WIDTH, HEIGHT };
actualExtent.width = std::max(std::min(surfaceCapabilities.maxImageExtent.width, actualExtent.width), surfaceCapabilities.minImageExtent.width);
actualExtent.height = std::max(std::min(surfaceCapabilities.maxImageExtent.height, actualExtent.height), surfaceCapabilities.minImageExtent.height);
return actualExtent;
}
}
// Swap Chain creation code
SwapChainSupportDetails swapChainSupportDetails = querySwapChainSupport(physicalDevice);
VkSurfaceFormatKHR surfaceFormat = chooseSwapChainSurfaceFormat(swapChainSupportDetails.formats);
VkPresentModeKHR presentMode = chooseSwapChainPresentMode(swapChainSupportDetails.presentModes);
VkExtent2D extent = chooseSwapChainExtent2D(swapChainSupportDetails.surfaceCapabilities);
uint32_t imageCount = swapChainSupportDetails.surfaceCapabilities.minImageCount + 1;
if (swapChainSupportDetails.surfaceCapabilities.maxImageCount > 0 && imageCount > swapChainSupportDetails.surfaceCapabilities.maxImageCount) {
imageCount = swapChainSupportDetails.surfaceCapabilities.minImageCount;
}
VkSwapchainCreateInfoKHR swapChainCreateInfo = {};
swapChainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
swapChainCreateInfo.surface = surface;
swapChainCreateInfo.minImageCount = imageCount;
swapChainCreateInfo.imageFormat = surfaceFormat.format;
swapChainCreateInfo.imageColorSpace = surfaceFormat.colorSpace;
swapChainCreateInfo.imageExtent = extent;
swapChainCreateInfo.imageArrayLayers = 1;
swapChainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
QueueFamilyIndices familyIndices = findQueueFamilies(physicalDevice);
uint32_t queueFamilyIndices[] = { familyIndices.graphicsFamily.value(), familyIndices.presentationFamily.value() };
if (familyIndices.graphicsFamily != familyIndices.presentationFamily) {
swapChainCreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
swapChainCreateInfo.queueFamilyIndexCount = 2;
swapChainCreateInfo.pQueueFamilyIndices = queueFamilyIndices;
}
else {
swapChainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
swapChainCreateInfo.queueFamilyIndexCount = 0;
swapChainCreateInfo.pQueueFamilyIndices = nullptr;
}
swapChainCreateInfo.preTransform = swapChainSupportDetails.surfaceCapabilities.currentTransform;
swapChainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
swapChainCreateInfo.presentMode = presentMode;
swapChainCreateInfo.clipped = VK_TRUE;
swapChainCreateInfo.oldSwapchain = VK_NULL_HANDLE;
if (vkCreateSwapchainKHR(device, &swapChainCreateInfo, nullptr, &swapChain) != VK_SUCCESS) {
throw std::runtime_error("Could not create swap chain");
}
I get the resulting structure:
Well, when creating the logical device one needs to set enabledExtensionCount to the actual number of required extensions and not 0 if one expects extensions to work. In my case, it was a simple edit failure. Here is the gem in my code:
createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
createInfo.ppEnabledExtensionNames = deviceExtensions.data();
createInfo.enabledExtensionCount = 0;
I figured it out by replacing every function from my code by the ones from the reference code until it worked. I'm a bit disappointed that the validation layers didn't catch this. Did I set them wrong? Is this something they should be catching?
EDIT: As pointed out by LIANG LIU, here is the initialization for deviceExtensions:
const std::vector<const char*> deviceExtensions = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME
};
Enable VK_KHR_SWAPCHAIN_EXTENSION_NAME when creating VkDevice
void VKRenderer::createVkLogicalDevice()
{
// device extensions
vector<const char*>::type deviceExtensionNames = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
// priorities
float queuePrioritys[2] = { 1.f, 1.f};
// graphics queue
VkDeviceQueueCreateInfo queueCreateInfos;
queueCreateInfos.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfos.pNext = nullptr;
queueCreateInfos.queueFamilyIndex = getGraphicsQueueFamilyIndex();
queueCreateInfos.queueCount = 1;
queueCreateInfos.pQueuePriorities = &queuePrioritys[0];
// device features
VkPhysicalDeviceFeatures deviceFeatures = {};
VkDeviceCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
createInfo.pNext = nullptr;
createInfo.pQueueCreateInfos = &queueCreateInfos;
createInfo.queueCreateInfoCount = 1;
createInfo.pEnabledFeatures = &deviceFeatures;
createInfo.enabledExtensionCount = deviceExtensionNames.size();
createInfo.ppEnabledExtensionNames = deviceExtensionNames.data();
// create logical device and retrieve graphics queue
if (VK_SUCCESS == vkCreateDevice(m_vkPhysicalDevice, &createInfo, nullptr, &m_vkDevice))
{
vkGetDeviceQueue(m_vkDevice, getGraphicsQueueFamilyIndex(), 0, &m_vkGraphicsQueue);
vkGetDeviceQueue(m_vkDevice, getPresentQueueFamilyIndex(), 0, &m_vkPresentQueue);
}
else
{
EchoLogError("Failed to create vulkan logical device!");
}
}
It looks like you are calling vkCreateDevice at the end of your code segment for creating the swapchain and passing in the VkSwapchainCreateInfo into it. Perhaps you want to call vkCreateSwapchainKHR instead, like:
if (vkCreateSwapchainKHR(device, &swapChainCreateInfo, nullptr, &swapChain) !=
VK_SUCCESS) {
throw std::runtime_error("failed to create swap chain");
}
If you are actually calling vkCreateSwapchainKHR, could you edit your question to indicate this?
I trying get the devices from pjsua2 , I got it get all devices, but do not got split in capture device and playback device.
void AudioController::load(){
Endpoint ep;
ep.libCreate();
// Initialize endpoint
EpConfig ep_cfg;
ep.libInit( ep_cfg );
AudDevManager &manager = ep.audDevManager();
manager.refreshDevs();
this->input.clear();
const AudioDevInfoVector &list = manager.enumDev();
for(unsigned int i = 0;list.size() != i;i++){
AudioDevInfo * info = list[i];
GtAudioDevice * a = new GtAudioDevice();
a->name = info->name.c_str();
a->deviceId = i;
qDebug() << info->name.c_str();
qDebug() << info->driver.c_str();
qDebug() << info->caps;
this->input.append(a);
}
ep.libDestroy();
}
This is my output:
Wave mapper
WMME
23
Microfone (Dispositivo de High
WMME
3
Alto-falantes (Dispositivo de H
WMME
21
You can check the fields inputCount and outputCount inside AudioDevInfo.
According the documentation:
unsigned inputCount
Maximum number of input channels supported by this device. If the
value is zero, the device does not support input operation (i.e. it is
a playback only device).
And
unsigned outputCount
Maximum number of output channels supported by this device. If the
value is zero, the device does not support output operation (i.e. it
is an input only device).
So you could do something like this:
for(unsigned int i = 0;list.size() != i;i++){
AudioDevInfo * info = list[i];
GtAudioDevice * a = new GtAudioDevice();
a->name = info->name.c_str();
a->deviceId = i;
if (info->inputCount > 0) {
a->captureDevice = true;
}
if (info->outputCount > 0) {
a->playbackDevice = true;
}
this->input.append(a);
}
Reference: http://www.pjsip.org/pjsip/docs/html/structpj_1_1AudioDevInfo.htm
Another way, you can check the field caps (capabilities). Something like this:
for (int i = 0; i < list.size(); i++)
{
AudioDevInfo * info = list[i];
if ((info.caps & (int)pjmedia_aud_dev_cap.PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY) != 0)
{
// Playback devices come here
}
if ((info.caps & (int)pjmedia_aud_dev_cap.PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY) != 0)
{
// Capture devices come here
}
}
caps is combined from these possible values:
enum pjmedia_aud_dev_cap {
PJMEDIA_AUD_DEV_CAP_EXT_FORMAT = 1,
PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY = 2,
PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY = 4,
PJMEDIA_AUD_DEV_CAP_INPUT_VOLUME_SETTING = 8,
PJMEDIA_AUD_DEV_CAP_OUTPUT_VOLUME_SETTING = 16,
PJMEDIA_AUD_DEV_CAP_INPUT_SIGNAL_METER = 32,
PJMEDIA_AUD_DEV_CAP_OUTPUT_SIGNAL_METER = 64,
PJMEDIA_AUD_DEV_CAP_INPUT_ROUTE = 128,
PJMEDIA_AUD_DEV_CAP_INPUT_SOURCE = 128,
PJMEDIA_AUD_DEV_CAP_OUTPUT_ROUTE = 256,
PJMEDIA_AUD_DEV_CAP_EC = 512,
PJMEDIA_AUD_DEV_CAP_EC_TAIL = 1024,
PJMEDIA_AUD_DEV_CAP_VAD = 2048,
PJMEDIA_AUD_DEV_CAP_CNG = 4096,
PJMEDIA_AUD_DEV_CAP_PLC = 8192,
PJMEDIA_AUD_DEV_CAP_MAX = 16384
}
i using this code to encode video stream using vp8 and i decided to give vp9 a try so i changed every thing with starts with vp_* from 8 to 9.
but the vp9 encoder always return a null packet although the encoder doesn't return any error.
here is the code i'am using for configuring.
vpx_codec_err_t error = vpx_codec_enc_config_default(vpx_codec_vp9_cx(), &enc_cfg, 0);
if(error != VPX_CODEC_OK)
return error;
enc_cfg.g_timebase.den = fps;
enc_cfg.rc_undershoot_pct = 95;
enc_cfg.rc_target_bitrate = bitrate;
enc_cfg.g_error_resilient = 1;
enc_cfg.kf_max_dist = 999999;
enc_cfg.rc_buf_initial_sz = 4000;
enc_cfg.rc_buf_sz = 6000;
enc_cfg.rc_buf_optimal_sz = 5000;
enc_cfg.rc_end_usage = VPX_CBR;
enc_cfg.g_h = height;
enc_cfg.g_w = width;
enc_cfg.rc_min_quantizer = 4;
enc_cfg.rc_max_quantizer = 56;
enc_cfg.g_threads = 4;
enc_cfg.g_pass = VPX_RC_ONE_PASS;
error = vpx_codec_enc_init(&codec, vpx_codec_vp9_cx(), &enc_cfg, 0);
if(error != VPX_CODEC_OK)
return error;
vpx_img_alloc(&vpx_image,VPX_IMG_FMT_I420 , width, height, 1);
configured = true;
return VPX_CODEC_OK;
and the code for the encoding
libyuv::RAWToI420(frame, vpx_image.d_w * 3, vpx_image.planes[VPX_PLANE_Y],vpx_image.stride[VPX_PLANE_Y],
vpx_image.planes[VPX_PLANE_U], vpx_image.stride[VPX_PLANE_U], vpx_image.planes[VPX_PLANE_V],
vpx_image.stride[VPX_PLANE_V], vpx_image.d_w, vpx_image.d_h);
const vpx_codec_cx_pkt_t *pkt;
vpx_codec_err_t error = vpx_codec_encode(&codec, &vpx_image, 0, 1, 0, VPX_DL_GOOD_QUALITY);
if(error != VPX_CODEC_OK)
return vector<byte>();
vpx_codec_iter_t iter = NULL;
if((pkt = vpx_codec_get_cx_data(&codec, &iter)))//always return null ?
{
if(pkt->kind == VPX_CODEC_CX_FRAME_PKT)
{
int length = pkt->data.frame.sz;
byte* buf = (byte*) pkt->data.frame.buf;
vector<byte> data(buf, buf + length);
return data;
}
return vector<byte>();
}
return vector<byte>();
the code is fully working if i'am using vp8 instead of 9, any help is welcomed
Just came across this post because I faced the same problem. Just for other to know: I solved it with setting
enc_cfg.g_lag_in_frames = 0;
This basically disallows the encoder to consume up to default 25 frames until it produces any output.