Q. FFMPEG - linux (Rasberry pi 4- Raspbian)- ошибка FFMPEG av_read_frame
Пользовательская среда
-Raspberry Pi 4B 4G x2
-arm32 и arm64
-OS: Распбиан
-gcc (Raspbian 8.3.0-6+rpi1) 8.3.0
-ffmpeg версии 4.1.4-1+rpt7~deb10u1, созданный с помощью gcc 8 (Raspbian 8.3.0-6+rpi1)
-IDE-visual studio 2017-соединение ssh
Доброе утро. У меня есть вопрос, опубликую его.
При установке Raspbian используется установленная библиотека FFMPEG.
Я хочу вывести видеодисплей - файл, закодированный в h264 с использованием gtk3.0.
Когда я открываю видеофайл, нахожу кодек и пытаюсь прочитать кадр, я получаю сообщение об ошибке и спрашиваю.
- Заполнение структурной памяти AVPacket? ошибка
2. Ошибка AVPacket-data: невозможно получить доступ к памяти по адресу 0xxxxxxxxxxxx>
- Ошибка значения AVPacket-stream_index. Значения stream_index и flags, по-видимому, поменялись местами.
мой исходный код и фотографии ошибок прилагаются. Спасибо.
case 1 ошибка stream_index (значение флагов ->stream_index)
введите описание изображения здесь
случай 2 ошибка доступа к памяти данных
введите описание изображения здесь
typedef struct _struMovContext2
{
AVFormatContext* pFormatCtx;
AVCodecContext* pVCodecCtx;
AVCodecContext* pACodecCtx;
AVCodec* pVCodec;
AVCodec* pACodec;
int nVStreamIndex;
int nAStreamIndex;
struct SwsContext* pSwsCtx;
GtkWidget* pImage;
pthread_t tID;
}MovContext2;
static MovContext2 Ctx;
static void pixmap_destroy_nf(guchar *pixels, gpointer data)
{
printf("Destroy pixmap - not sure how\n");
}
static void* PlayBackGround(void* pData)
{
MovContext2* pCtx = NULL;
GdkPixbuf* pixbuf = NULL;
GError* error = NULL;
int nFrameWidth, nFrameHeight;
int nFrameEos = 0;
AVFrame* pFrame = NULL;
AVFrame* pPicture_RGB = NULL;
AVPacket packet;
uint8_t* pBuffer = NULL;
cairo_surface_t* surface = NULL;
cairo_t* cr = NULL;
//if ((pCtx = static_cast<MovContext2*>(pData)) == NULL)
pCtx = &Ctx;
if(pCtx == NULL)
{
av_log(NULL, AV_LOG_ERROR, "Couldn't get context struct - Data nullpointer");
return NULL;
}
printf("In Thread - PlayBackGround\n");
if ((pFrame = av_frame_alloc()) == NULL)
{
av_log(NULL, AV_LOG_ERROR, "Couldn't alloc frame");
return NULL;
}
if ((pPicture_RGB = av_frame_alloc()) == NULL)
{
av_log(NULL, AV_LOG_ERROR, "Couldn't alloc Picture RGB");
return NULL;
}
if ((pBuffer = (uint8_t*)malloc(avpicture_get_size(AV_PIX_FMT_RGB24, 1920, 1080))) == NULL)
{
av_log(NULL, AV_LOG_ERROR, "Couldn't malloc data buffer");
return NULL;
}
avpicture_fill((AVPicture*)pPicture_RGB, pBuffer, AV_PIX_FMT_RGB24, 1920, 1080);*/
av_init_packet(&packet);
packet.data = NULL;
packet.size = 0;
//packet = *av_packet_alloc();
while (av_read_frame(pCtx->pFormatCtx, &packet) >= 0)
{
printf("Read packet stream index : %d\n", packet.stream_index);
if (packet.stream_index == pCtx->nVStreamIndex)
{
//av_usleep(33670);
printf("Decoding to frame start\n");
if (avcodec_decode_video2(pCtx->pVCodecCtx, pFrame, &nFrameEos, &packet) < 0)
{
av_log(NULL, AV_LOG_ERROR, "Decod video error");
return NULL;
}
printf("Decoding to frame end\n");
nFrameWidth = pCtx->pVCodecCtx->width;
nFrameHeight = pCtx->pVCodecCtx->height;
printf("frame Width : %d, Height : %d\n", nFrameWidth, nFrameHeight);
pCtx->pSwsCtx = sws_getContext(nFrameWidth,
nFrameHeight,
pCtx->pVCodecCtx->pix_fmt,
nFrameWidth,
nFrameHeight,
AV_PIX_FMT_RGB24,
SWS_BICUBIC,
NULL, NULL, NULL);
printf("sws Get context\n");
if (nFrameEos > 0)
{
sws_scale( pCtx->pSwsCtx,
pFrame->data,
pFrame->linesize,
0,
nFrameHeight,
pPicture_RGB->data,
pPicture_RGB->linesize);
printf("sws set scale\n");
pixbuf = gdk_pixbuf_new_from_data(pPicture_RGB->data[0],
GDK_COLORSPACE_RGB,
0,
8,
nFrameWidth,
nFrameHeight,
pPicture_RGB->linesize[0],
pixmap_destroy_nf,
NULL);
printf("create pixbuf from frame data\n");
gtk_image_set_from_pixbuf((GtkImage*)pCtx->pImage, pixbuf);
g_object_unref(pixbuf);
cairo_surface_destroy(surface);
cairo_destroy(cr);
//gdk_threads_leave();
}
av_free_packet(&packet);
}
}
printf("Exit Thread\n");
return NULL;
}
int main(int argc, char *argv[])
{
GtkWidget* overlay;
GtkWidget* eventBox;
GError* err = NULL;
CMonitorManager* pManager;
GdkRectangle Rect;
char* pFileURI = "/home/pi/test.mp4";
//char* pFileURI = "/home/ubuntu/test.mp4";
//char* pFileURI = "/home/ubuntu/cev.avi";
int nIndex;
//MovContext2 Ctx;
//XInitThreads();
memset(&Ctx, 0x00, sizeof(Ctx));
av_register_all();
if (avformat_open_input(&Ctx.pFormatCtx, pFileURI, NULL, NULL) != 0)
{
av_log(NULL, AV_LOG_ERROR, "Couldn't open file");
return FALSE;
}
printf("C - open uri\n");
if (avformat_find_stream_info(Ctx.pFormatCtx, NULL) != 0)
{
av_log(NULL, AV_LOG_ERROR, "Couldn't find stream information");
return FALSE;
}
printf("C - find stream info\n");
av_dump_format(Ctx.pFormatCtx, 0, pFileURI, 0);
printf("C - media dump\n");
Ctx.nVStreamIndex = av_find_best_stream(Ctx.pFormatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
if (Ctx.nVStreamIndex == AVERROR_STREAM_NOT_FOUND)
{
for (nIndex = 0; nIndex < Ctx.pFormatCtx->nb_streams; nIndex++)
{
if (Ctx.pFormatCtx->streams[nIndex]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
Ctx.nVStreamIndex = nIndex;
break;
}
}
if (Ctx.nVStreamIndex < 0)
{
av_log(NULL, AV_LOG_ERROR, "Didn't find a video stream");
return FALSE;
}
}
printf("C - get video stream index\n");
Ctx.nAStreamIndex = av_find_best_stream(Ctx.pFormatCtx, AVMEDIA_TYPE_AUDIO, Ctx.nVStreamIndex, -1, NULL, 0);
if (Ctx.nAStreamIndex == AVERROR_STREAM_NOT_FOUND)
{
for (nIndex = 0; nIndex < Ctx.pFormatCtx->nb_streams; nIndex++)
{
if (Ctx.pFormatCtx->streams[nIndex]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
{
Ctx.nAStreamIndex = nIndex;
break;
}
}
if (Ctx.nAStreamIndex < 0)
{
av_log(NULL, AV_LOG_ERROR, "Didn't find a audio stream");
}
}
printf("C - get audio stream index\n");
if ((Ctx.pFormatCtx->streams[Ctx.nVStreamIndex]->codecpar = avcodec_parameters_alloc()) == NULL)
{
av_log(NULL, AV_LOG_ERROR, "Couldn't alloc video codec parameters");
return FALSE;
}
avcodec_parameters_from_context(Ctx.pFormatCtx->streams[Ctx.nVStreamIndex]->codecpar,
Ctx.pFormatCtx->streams[Ctx.nVStreamIndex]->codec);
printf("C - video codec parameter alloc\n");
Ctx.pVCodec = avcodec_find_decoder(Ctx.pFormatCtx->streams[Ctx.nVStreamIndex]->codecpar->codec_id);
printf("C - find video codec %s \n", Ctx.pVCodec->long_name);
Ctx.pVCodecCtx = avcodec_alloc_context3(Ctx.pVCodec);
avcodec_parameters_to_context(Ctx.pVCodecCtx, Ctx.pFormatCtx->streams[Ctx.nVStreamIndex]->codecpar);
if (avcodec_open2(Ctx.pVCodecCtx, Ctx.pVCodec, NULL) < 0)
{
av_log(NULL, AV_LOG_ERROR, "Could not open video codec");
return FALSE;
}
printf("C - video codec context oepn\n");
if (Ctx.nAStreamIndex > 0)
{
if ((Ctx.pFormatCtx->streams[Ctx.nAStreamIndex]->codecpar = avcodec_parameters_alloc()) != NULL)
{
avcodec_parameters_from_context(Ctx.pFormatCtx->streams[Ctx.nAStreamIndex]->codecpar,
Ctx.pFormatCtx->streams[Ctx.nAStreamIndex]->codec);
printf("C - audio codec parameter alloc\n");
Ctx.pACodec = avcodec_find_decoder(Ctx.pFormatCtx->streams[Ctx.nAStreamIndex]->codecpar->codec_id);
printf("C - find audio codec\n");
Ctx.pACodecCtx = avcodec_alloc_context3(Ctx.pACodec);
if (avcodec_open2(Ctx.pACodecCtx, Ctx.pACodec, NULL) < 0) {
av_log(NULL, AV_LOG_ERROR, "Could not open audio codec");
}
printf("C - audio codec context oepn\n");
}
else
{
av_log(NULL, AV_LOG_ERROR, "Couldn't alloc video codec parameters");
}
}
Ctx.pVCodecCtx->width = 1920;
Ctx.pVCodecCtx->height = 1080;
Ctx.pSwsCtx = sws_getContext(Ctx.pVCodecCtx->width,
Ctx.pVCodecCtx->height,
Ctx.pVCodecCtx->pix_fmt,
Ctx.pVCodecCtx->width,
Ctx.pVCodecCtx->height,
AV_PIX_FMT_YUV420P,
SWS_BILINEAR,
NULL,
NULL,
NULL);
pthread_create(&Ctx.tID, NULL, PlayBackGround, &Ctx);
GtkWidget *window;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
Ctx.pImage = gtk_image_new();
gtk_container_add(GTK_CONTAINER(window), Ctx.pImage);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 1920, 1080);
gtk_widget_show_all(window);
gtk_main();
return 0;
}