2017-10-03 5 views
1

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à.

+0

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

+0

@Programmer, j'ai ajouté toutes les informations manquantes à la question principale. J'ai fait tout ce que vous avez dit dans cette réponse. –

+0

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

Répondre

0

La raison pour laquelle sws_scale échouait était de transmettre une hauteur et une largeur de source incorrectes pour sws_getContext et pour sws_scale. Vous devriez passer les dimensions dans la méthode ou les valeurs hardcore dans Unity.

Egalement sws_scale renvoie la hauteur de la tranche de sortie, pas une erreur.