forked from ML-Cai/IPcam
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdecoder.c
More file actions
119 lines (99 loc) · 3.58 KB
/
decoder.c
File metadata and controls
119 lines (99 loc) · 3.58 KB
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
#include <stdio.h>
#include <stdlib.h>
#define __STDC_CONSTANT_MACROS
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <libavutil/rational.h>
#include "decoder.h"
/* ------------------------------------------------------------ */
static int CAMERA_WIDTH = 0;
static int CAMERA_HEIGHT =0;
/* ------------------------------------------------------------ */
struct decoder_struct VOD_decoder ;
/* ------------------------------------------------------------ */
void video_decoder_init(int width, int hegiht, int pixel_fmt)
{
CAMERA_WIDTH = width ;
CAMERA_HEIGHT = hegiht ;
// VOD_decoder.codec = avcodec_find_decoder(AV_CODEC_ID_H264);
VOD_decoder.codec = avcodec_find_decoder(AV_CODEC_ID_MPEG4);
if (!VOD_decoder.codec) {
perror("codec not found\n");
goto ERROR_EXIT;
}
/* alloc Frame buffer */
int numBytes = avpicture_get_size(PIX_FMT_RGB24, CAMERA_WIDTH, CAMERA_HEIGHT);
VOD_decoder.buffer = (unsigned char *)av_malloc(sizeof(unsigned char) * numBytes);
/* alloc FFmpeg resource*/
VOD_decoder.c_context= avcodec_alloc_context3(VOD_decoder.codec);
VOD_decoder.frame_RGB24 = av_frame_alloc();
VOD_decoder.frame_YUV420P = av_frame_alloc();
avpicture_fill((AVPicture *)VOD_decoder.frame_RGB24, VOD_decoder.buffer, PIX_FMT_RGB24, CAMERA_WIDTH, CAMERA_HEIGHT);
/* put sample parameters */
VOD_decoder.c_context->bit_rate = CAMERA_WIDTH * CAMERA_HEIGHT * 4;
/* resolution must be a multiple of two */
VOD_decoder.c_context->width = CAMERA_WIDTH;
VOD_decoder.c_context->height = CAMERA_HEIGHT;
/* frames per second */
VOD_decoder.c_context->time_base.num = 1 ;
VOD_decoder.c_context->time_base.den = 30;
VOD_decoder.c_context->gop_size = 10; /* emit one intra frame every ten frames */
VOD_decoder.c_context->max_b_frames = 0;
VOD_decoder.c_context->thread_count = 1;
VOD_decoder.c_context->pix_fmt = PIX_FMT_YUV420P;
/* open it */
if (avcodec_open2(VOD_decoder.c_context, VOD_decoder.codec, NULL) < 0) {
fprintf(stderr, "could not open codec\n");
goto ERROR_EXIT;
}
/* prepare image conveter */
VOD_decoder.img_convert_ctx = sws_getContext(CAMERA_WIDTH, CAMERA_HEIGHT, PIX_FMT_YUV420P,
CAMERA_WIDTH, CAMERA_HEIGHT, PIX_FMT_RGB24,
SWS_POINT, NULL, NULL, NULL);
if(VOD_decoder.img_convert_ctx == NULL) {
fprintf(stderr, "Cannot initialize the conversion context!\n");
}
printf("Decoder init finish\n");
return ;
ERROR_EXIT:
getchar();
exit(1);
}
/* --------------------------------------------------------------------------------------- */
void video_decoder_release()
{
free(VOD_decoder.buffer);
avcodec_close(VOD_decoder.c_context);
av_free(VOD_decoder.frame_RGB24);
av_free(VOD_decoder.frame_YUV420P);
}
/* --------------------------------------------------------------------------------------- */
int video_decoder(unsigned char *raw_buf ,int buf_size, unsigned char **ret_buf)
{
AVPacket VOD_pkt;
int delen=0;
int got_picture =0;
av_init_packet(&VOD_pkt);
VOD_pkt.data = raw_buf;
VOD_pkt.size = buf_size;
if (VOD_pkt.size == 0) {
fprintf(stderr, "0 size packet\n");
return 0;
}
delen = avcodec_decode_video2(VOD_decoder.c_context, VOD_decoder.frame_YUV420P, &got_picture, &VOD_pkt);
if (delen < 0) {
fprintf(stderr, "Error while decoding frame \n");
return 0;
}
if (got_picture) {
/* format to RGB */
sws_scale(VOD_decoder.img_convert_ctx,
VOD_decoder.frame_YUV420P->data, VOD_decoder.frame_YUV420P->linesize ,
0, VOD_decoder.c_context->height,
VOD_decoder.frame_RGB24->data, VOD_decoder.frame_RGB24->linesize);
/* feedback data */
*ret_buf = VOD_decoder.frame_RGB24->data[0];
}
return 1;
}