-
Notifications
You must be signed in to change notification settings - Fork 16
/
data_source_ocv_avcodec.cpp
120 lines (97 loc) · 3.27 KB
/
data_source_ocv_avcodec.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#define __STDC_CONSTANT_MACROS
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
}
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include "config.h"
#include "data_source_ocv_avcodec.h"
#include "opencv/highgui.h"
data_source_ocv_avcodec::data_source_ocv_avcodec(const char * name)
{
int numBytes;
m_name = strdup( name );
cvNamedWindow( m_name, CV_WINDOW_AUTOSIZE);
avcodec_register_all();
// Find the decoder for the video stream
pCodec=avcodec_find_decoder(AV_CODEC_ID_H264);
if(pCodec==NULL)
{
printf("No codec\n");
}
// Open codec
pCodecCtx = avcodec_alloc_context3( pCodec );
pCodecCtx->pix_fmt=AV_PIX_FMT_YUV420P;
pCodecCtx->width=WIDTH;
pCodecCtx->height=HEIGHT;
if(avcodec_open2(pCodecCtx, pCodec,NULL)<0)
{
printf("couldn't open codec\n");
}
// Hack to correct wrong frame rates that seem to be generated by some codecs
if(pCodecCtx->time_base.num>1000 && pCodecCtx->time_base.den==1)
pCodecCtx->time_base.den=1000;
// Allocate video frame
pFrame=av_frame_alloc();
// Allocate an AVFrame structure
pFrameRGB=av_frame_alloc();
if(pFrameRGB==NULL)
{
printf("Frame alloc failed\n");
}
// Determine required buffer size and allocate buffer
numBytes=avpicture_get_size(AV_PIX_FMT_RGB24, pCodecCtx->width,pCodecCtx->height);
buffer=malloc(numBytes);
// Assign appropriate parts of buffer to image planes in pFrameRGB
avpicture_fill((AVPicture *)pFrameRGB, (uint8_t*)buffer, AV_PIX_FMT_RGB24,pCodecCtx->width, pCodecCtx->height);
}
data_source_ocv_avcodec::~data_source_ocv_avcodec()
{
cvDestroyWindow( m_name );
free( (void*)m_name );
// Free the RGB image
free(buffer);
av_free(pFrameRGB);
// Close the codec
// Free the YUV frame
av_free(pFrame);
avcodec_close(pCodecCtx);
}
void data_source_ocv_avcodec::write( const uint8_t * data, size_t bytes )
{
int frameFinished=0;
// Decode video frame
AVPacket avpkt;
memset( &avpkt, 0x00, sizeof avpkt );
avpkt.data=(uint8_t*)data;
avpkt.size=bytes;
avcodec_decode_video2(pCodecCtx, pFrame,&frameFinished, &avpkt );
// Did we get a video frame?
if(frameFinished)
{
IplImage * output_image = cvCreateImageHeader(cvSize(pCodecCtx->width,pCodecCtx->height),IPL_DEPTH_8U,3);
static struct SwsContext *img_convert_ctx;
// Convert the image into YUV format that SDL uses
if(img_convert_ctx == NULL)
{
int w = pCodecCtx->width;
int h = pCodecCtx->height;
img_convert_ctx = sws_getContext(w, h, pCodecCtx->pix_fmt, w, h, AV_PIX_FMT_BGR24, SWS_FAST_BILINEAR ,NULL, NULL, NULL);
if(img_convert_ctx == NULL)
{
fprintf(stderr, "Cannot initialize the conversion context!\n");
exit(1);
}
}
sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
// Blit
output_image->imageData = (char*)pFrameRGB->data[0];
cvShowImage(m_name,output_image);
cvWaitKey(1);
output_image->imageData = NULL;
cvReleaseImageHeader( &output_image );
}
}