J'essaie de créer un enregistreur vidéo à l'intérieur du lecteur Unity en utilisant FFmpeg.Conversion Unity texture2d en YUV420P pour ffmpeg
J'ai ici des extraits de code:
Unité, C#:
Texture2D frameTexture = new Texture2D(frameWidth, frameHeight, TextureFormat.RGB24, false);
//...
frameTexture.ReadPixels(new Rect(0, 0, frameWidth, frameHeight), 0, 0, false);
frameTexture.Apply();
//.....
byte[] pixels = frameTexture.GetRawTextureData();
AddFrame(pixels, pixels.Length, libApi);
//DLL Function Declaration
[DllImport("VideoCapture", CallingConvention = CallingConvention.Cdecl)]
static extern void AddFrame(byte[] data, int size, System.IntPtr api);
C++ Code:
__declspec(dllexport) void AddFrame(uint8_t *data, int size, VideoCapture *vc) {
vc->AddFrame(data, size);
}
void VideoCapture::AddFrame(uint8_t *data, int size) {
Log("\nAdding frame\n");
int err;
if (!videoFrame) {
Log("Allocating Video Frame\n");
videoFrame = av_frame_alloc();
videoFrame->format = AV_PIX_FMT_YUV420P;
videoFrame->width = cctx->width;
videoFrame->height = cctx->height;
if ((err = av_frame_get_buffer(videoFrame, 32)) < 0) {
Debug("Failed to allocate picture", err);
return;
}
}
if (!swsCtx) {
Log("Creating SWS context\n");
swsCtx = sws_getContext(cctx->width, cctx->height, AV_PIX_FMT_RGB24, cctx->width, cctx->height, AV_PIX_FMT_YUV420P, 0, 0, 0, 0);
}
uint8_t * inData[1] = { data };
int inLinesize[1] = { 3 * cctx->width };
Log("Scaling data\n");
// From RGB to YUV
if ((err = sws_scale(swsCtx, inData, inLinesize, 0, cctx->height, videoFrame->data, videoFrame->linesize)) < 0) {
Debug("Failed to scale img", err);
return;
}
...........
lecteur tombe en panne Unity quand il fait "sws_scale".
Journaux de l'unité:
ERROR: SymGetSymFromAddr64, GetLastError: 'Attempt to access invalid address.' (Address: 00007FF8437B49A6)
0x00007FF8437B49A6 (swscale-4)
ERROR: SymGetSymFromAddr64, GetLastError: 'Attempt to access invalid address.' (Address: 00007FF8437B2982)
0x00007FF8437B2982 (swscale-4)
0x00007FF8437E78A6 (swscale-4) sws_get_class
0x00007FF8437E8E47 (swscale-4) sws_scale
Je pensais que sa cause de « sws_get_class », mais il fonctionne si je l'appelle directement cette fonction. Cela fonctionne aussi si je passe des données vides dans 'sws_scale', se plaignant seulement que c'est NULL. Donc, la raison en est dans les données elles-mêmes, mais je ne sais pas ce qui ne va pas.
J'ai également essayé d'encoder la texture en JPG et PNG, tableau épinglé dans la mémoire, mais le résultat n'a pas changé.
Merci à l'avance
UPD :::
fonction Changed DLL appellent à
unsafe void AddFrame(byte[] data)
{
fixed (byte* p = data)
{
AddFrame((IntPtr)p, data.Length, customLib);
}
}
//Function declaration
static extern void AddFrame(IntPtr data, int size, System.IntPtr api);
Mais l'erreur est toujours là.
Votre fonction C# 'AddFrame' prend 3 params mais votre fonction C++' AddFrame' n'a que 2 params .... Aussi, vous n'épinglez pas le tableau. Vous ignorez fondamentalement ce que j'ai dit dans ma réponse [autre] (https://stackoverflow.com/a/46527921/3785314). – Programmer
@Programmer, j'ai ajouté toutes les informations manquantes à la question principale. J'ai fait tout ce que vous avez dit dans cette réponse. –
Ne le supprimez pas à l'avenir même si vous rencontrez d'autres problèmes. Si ce n'est pas nécessaire je ne passerais pas de temps à écrire ça. quant à votre problème, je ne sais pas vraiment puisque la plupart des choses que j'avais à l'esprit sont maintenant éliminées mais comment savez-vous que le problème vient de la ligne 'sws_scale'? – Programmer