Copy link to clipboard
Copied
Trying to get the footage path to be used in a stream for my plugin, however running into some trouble converting a A_UTF16Char into a standard string. Was trying conversions with wstring_convert, but this keeps giving me access violation errors. Does anyone have a good system for this? Thanks!
std::string utf16_to_utf8(std::wstring utf16_string)
{
return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t>{}.to_bytes(utf16_string);
}
[...]
AEGP_ItemH layer_itemH = NULL;
AEGP_MemHandle pathH;
AEGP_ItemType item_type;
AEGP_FootageH layer_footageH = NULL;
ERR(suites.LayerSuite7()->AEGP_GetLayerSourceItem(layerH, &layer_itemH));
ERR(suites.ItemSuite6()->AEGP_GetItemType(layer_itemH, &item_type));
ERR(suites.FootageSuite5()->AEGP_GetMainFootageFromItem(layer_itemH, &layer_footageH));
ERR(suites.FootageSuite5()->AEGP_GetFootagePath(layer_footageH, 0, AEGP_FOOTAGE_MAIN_FILE_INDEX, &pathH));
if (item_type == AEGP_ItemType_FOOTAGE && !err && pathH) {
std::wstring res16;
ERR(suites.MemorySuite1()->AEGP_LockMemHandle(pathH, reinterpret_cast<void**>(&res16)));
if (res16.size() > 0) {
std::string resStr = utf16_to_utf8(res16);
[...]
}
ERR(suites.MemorySuite1()->AEGP_UnlockMemHandle(pathH));
}
Thanks Toby! That may have solved some of the sporadic issues I've been having. I'm seeing mixed uses of UnlockMemHandle() and FreeMemHandle() in the docs and SDK samples, but using both seems to work for now. Here's what's working for me now:
...wchar_t* res16B;
AEGP_MemHandle pathH;
ERR(suites.FootageSuite5()->AEGP_GetFootagePath(layer_footageH, 0, AEGP_FOOTAGE_MAIN_FILE_INDEX, &pathH));
ERR(suites.MemorySuite1()->AEGP_LockMemHandle(pathH, reinterpret_cast<void**>(&res16B)));
std::wstring ws(res16
Copy link to clipboard
Copied
you can't lock pathH directly into a std::wstring. you need to lock it into
"A_UTF16Char *tempC";
you must also later delete pathH and not only unlock it.
On Wed, May 29, 2019 at 2:50 AM justintaylor <forums_noreply@adobe.com>
Copy link to clipboard
Copied
Yea, wstring wasn't the answer. I ended up using wchar_t since I haven't found any other way of converting A_UTF16Char
std::string UTF16_to_String(wchar_t* utf_string)
{
std::vector<char> tmp_buff;
_locale_t locale = _create_locale(LC_ALL, "en");
size_t len;
{
_wcstombs_s_l(&len, NULL, 0, utf_string, 0, locale);
tmp_buff.resize(len + 1);
_wcstombs_s_l(NULL, &tmp_buff[0], len, utf_string, len, locale);
if (&tmp_buff[0] == NULL)
return "";
else
return &tmp_buff[0];
}
}
[...]
wchar_t* res16B;
AEGP_MemHandle pathH;
ERR(suites.FootageSuite5()->AEGP_GetFootagePath(layer_footageH, 0, AEGP_FOOTAGE_MAIN_FILE_INDEX, &pathH));
ERR(suites.MemorySuite1()->AEGP_LockMemHandle(pathH, reinterpret_cast<void**>(&res16B)));
ERR(suites.MemorySuite1()->AEGP_FreeMemHandle(pathH));
std::string resStr = UTF16_to_String(res16B);
This is working for now anyway. Only saw examples in the examples of freeing (not unlocking) a memory handle after using it, but you're saying I need to delete pathH as well? I haven't had any memory leak errors with this method yet...
Copy link to clipboard
Copied
Actually, _wcstombs was crashing if I changed interpret settings with preview turned on for some reason. Here's a more simplified conversion.
wchar_t* res16B;
AEGP_MemHandle pathH;
ERR(suites.FootageSuite5()->AEGP_GetFootagePath(layer_footageH, 0, AEGP_FOOTAGE_MAIN_FILE_INDEX, &pathH));
ERR(suites.MemorySuite1()->AEGP_LockMemHandle(pathH, reinterpret_cast<void**>(&res16B)));
ERR(suites.MemorySuite1()->AEGP_FreeMemHandle(pathH));
std::wstring ws(res16B);
std::string resStr(ws.begin(), ws.end());
This seems to work pretty well now, but I'm all ears if someone has a more straightforward method.
Copy link to clipboard
Copied
You should lock using the handle, then use the pointer you are given (i.e. copy or convert the content it points to), then unlock/free the handle again.
In your code, you are locking and then freeing and then using the now invalid pointer res16B. This might still work most of the time since the memory the variable points to hasn't been overwritten yet in that short amount of time (probably), but it is a horrendous bug to track down should it happen, believe me. So it is probably best to put the AEGP_FreeMemHandle after all your pointer operations.
Copy link to clipboard
Copied
Thanks Toby! That may have solved some of the sporadic issues I've been having. I'm seeing mixed uses of UnlockMemHandle() and FreeMemHandle() in the docs and SDK samples, but using both seems to work for now. Here's what's working for me now:
wchar_t* res16B;
AEGP_MemHandle pathH;
ERR(suites.FootageSuite5()->AEGP_GetFootagePath(layer_footageH, 0, AEGP_FOOTAGE_MAIN_FILE_INDEX, &pathH));
ERR(suites.MemorySuite1()->AEGP_LockMemHandle(pathH, reinterpret_cast<void**>(&res16B)));
std::wstring ws(res16B);
std::string resStr(ws.begin(), ws.end());
ERR(suites.MemorySuite1()->AEGP_UnlockMemHandle(pathH));
ERR(suites.MemorySuite1()->AEGP_FreeMemHandle(pathH));
Copy link to clipboard
Copied
Every AEGP_LockMemHandle all should be paired with an AEGP_UnlockMemHandle call, and every AEGP_NewMemHandle call should have a corresponding AEGP_FreeMemHandle call somewhere further down the line.
However, there are some SDK function calls that implicitly do one of these things, e.g. the AEGP_GetFootagePath() function internally allocates a new handle already using AEGP_NewMemHandle and passes that back to you. It is then your task to call AEGP_FreeMemHandle when you no longer need it!
So, how do you know when you should free a handle and when not? The only way is to look in the SKD manual or directly in the headers. For AEGP_GetFootagePath, it says for example: "Retrieves the footage path. The path is a handle to a NULL-terminated A_UTF16Char string, and must be disposed with AEGP_FreeMemHandle."
Copy link to clipboard
Copied
Got it, thanks for clarifying!
So in this case I do need to use both Unlock and Free since I'm creating a new handle with AEGP_GetFootagePath() (that needs to be freed with AEGP_FreeMemHandle()) and also locking memory with AEGP_LockMemHandle() (that needs to be unlocked with AEGP_UnlockMemHandle()).
Copy link to clipboard
Copied
Correct