2
mediastreamer2 library - modular sound and video processing and streaming
3
Copyright (C) 2010 Belledonne Communications SARL
4
Author: Simon Morlat <simon.morlat@linphone.org>
6
This program is free software; you can redistribute it and/or
7
modify it under the terms of the GNU General Public License
8
as published by the Free Software Foundation; either version 2
9
of the License, or (at your option) any later version.
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
#include "mediastreamer2/msfilter.h"
22
#include "mediastreamer2/rfc3984.h"
23
#include "mediastreamer2/msvideo.h"
24
#include "mediastreamer2/msticker.h"
26
#include "ffmpeg-priv.h"
31
typedef struct _DecData{
34
Rfc3984Context unpacker;
36
struct SwsContext *sws_ctx;
37
AVCodecContext av_context;
38
unsigned int packet_num;
41
uint64_t last_error_reported_time;
42
bool_t first_image_decoded;
45
static void ffmpeg_init(){
46
static bool_t done=FALSE;
48
#ifdef FF_API_AVCODEC_INIT
51
avcodec_register_all();
56
static void dec_open(DecData *d){
59
codec=avcodec_find_decoder(CODEC_ID_H264);
60
if (codec==NULL) ms_fatal("Could not find H264 decoder in ffmpeg.");
61
avcodec_get_context_defaults(&d->av_context);
62
error=avcodec_open(&d->av_context,codec);
64
ms_fatal("avcodec_open() failed.");
68
static void dec_init(MSFilter *f){
69
DecData *d=(DecData*)ms_new(DecData,1);
75
rfc3984_init(&d->unpacker);
80
d->bitstream_size=65536;
81
d->bitstream=ms_malloc0(d->bitstream_size);
82
d->last_error_reported_time=0;
86
static void dec_preprocess(MSFilter* f) {
87
DecData *s=(DecData*)f->data;
88
s->first_image_decoded = FALSE;
91
static void dec_reinit(DecData *d){
92
avcodec_close(&d->av_context);
96
static void dec_uninit(MSFilter *f){
97
DecData *d=(DecData*)f->data;
98
rfc3984_uninit(&d->unpacker);
99
avcodec_close(&d->av_context);
100
if (d->yuv_msg) freemsg(d->yuv_msg);
101
if (d->sps) freemsg(d->sps);
102
if (d->pps) freemsg(d->pps);
103
ms_free(d->bitstream);
107
static mblk_t *get_as_yuvmsg(MSFilter *f, DecData *s, AVFrame *orig){
108
AVCodecContext *ctx=&s->av_context;
110
if (s->outbuf.w!=ctx->width || s->outbuf.h!=ctx->height){
111
if (s->sws_ctx!=NULL){
112
sws_freeContext(s->sws_ctx);
117
ms_message("Getting yuv picture of %ix%i",ctx->width,ctx->height);
118
s->yuv_msg=ms_yuv_buf_alloc(&s->outbuf,ctx->width,ctx->height);
119
s->outbuf.w=ctx->width;
120
s->outbuf.h=ctx->height;
121
s->sws_ctx=sws_getContext(ctx->width,ctx->height,ctx->pix_fmt,
122
ctx->width,ctx->height,PIX_FMT_YUV420P,SWS_FAST_BILINEAR,
125
#if LIBSWSCALE_VERSION_INT >= AV_VERSION_INT(0,9,0)
126
if (sws_scale(s->sws_ctx,(const uint8_t * const *)orig->data,orig->linesize, 0,
127
ctx->height, s->outbuf.planes, s->outbuf.strides)<0){
129
if (sws_scale(s->sws_ctx,(uint8_t **)orig->data,orig->linesize, 0,
130
ctx->height, s->outbuf.planes, s->outbuf.strides)<0){
132
ms_error("%s: error in sws_scale().",f->desc->name);
134
return dupmsg(s->yuv_msg);
137
static void update_sps(DecData *d, mblk_t *sps){
143
static void update_pps(DecData *d, mblk_t *pps){
146
if (pps) d->pps=dupb(pps);
151
static bool_t check_sps_change(DecData *d, mblk_t *sps){
154
ret=(msgdsize(sps)!=msgdsize(d->sps)) || (memcmp(d->sps->b_rptr,sps->b_rptr,msgdsize(sps))!=0);
156
ms_message("SPS changed ! %i,%i",msgdsize(sps),msgdsize(d->sps));
161
ms_message("Receiving first SPS");
167
static bool_t check_pps_change(DecData *d, mblk_t *pps){
170
ret=(msgdsize(pps)!=msgdsize(d->pps)) || (memcmp(d->pps->b_rptr,pps->b_rptr,msgdsize(pps))!=0);
172
ms_message("PPS changed ! %i,%i",msgdsize(pps),msgdsize(d->pps));
176
ms_message("Receiving first PPS");
183
static void enlarge_bitstream(DecData *d, int new_size){
184
d->bitstream_size=new_size;
185
d->bitstream=ms_realloc(d->bitstream,d->bitstream_size);
188
static int nalusToFrame(DecData *d, MSQueue *naluq, bool_t *new_sps_pps){
190
uint8_t *dst=d->bitstream,*src,*end;
192
bool_t start_picture=TRUE;
195
end=d->bitstream+d->bitstream_size;
196
while((im=ms_queue_get(naluq))!=NULL){
198
nal_len=im->b_wptr-src;
199
if (dst+nal_len+100>end){
200
int pos=dst-d->bitstream;
201
enlarge_bitstream(d, d->bitstream_size+nal_len+100);
202
dst=d->bitstream+pos;
203
end=d->bitstream+d->bitstream_size;
205
if (src[0]==0 && src[1]==0 && src[2]==0 && src[3]==1){
206
int size=im->b_wptr-src;
207
/*workaround for stupid RTP H264 sender that includes nal markers */
208
memcpy(dst,src,size);
211
nalu_type=(*src) & ((1<<5)-1);
213
*new_sps_pps=check_sps_change(d,im) || *new_sps_pps;
215
*new_sps_pps=check_pps_change(d,im) || *new_sps_pps;
216
if (start_picture || nalu_type==7/*SPS*/ || nalu_type==8/*PPS*/ ){
221
/*prepend nal marker*/
226
while(src<(im->b_wptr-3)){
227
if (src[0]==0 && src[1]==0 && src[2]<3){
241
return dst-d->bitstream;
244
static void dec_process(MSFilter *f){
245
DecData *d=(DecData*)f->data;
249
ms_queue_init(&nalus);
250
while((im=ms_queue_get(f->inputs[0]))!=NULL){
251
/*push the sps/pps given in sprop-parameter-sets if any*/
252
if (d->packet_num==0 && d->sps && d->pps){
253
mblk_set_timestamp_info(d->sps,mblk_get_timestamp_info(im));
254
mblk_set_timestamp_info(d->pps,mblk_get_timestamp_info(im));
255
rfc3984_unpack(&d->unpacker,d->sps,&nalus);
256
rfc3984_unpack(&d->unpacker,d->pps,&nalus);
260
rfc3984_unpack(&d->unpacker,im,&nalus);
261
if (!ms_queue_empty(&nalus)){
264
bool_t need_reinit=FALSE;
266
size=nalusToFrame(d,&nalus,&need_reinit);
270
end=d->bitstream+size;
275
avcodec_get_frame_defaults(&orig);
276
av_init_packet(&pkt);
279
len=avcodec_decode_video2(&d->av_context,&orig,&got_picture,&pkt);
281
ms_warning("ms_AVdecoder_process: error %i.",len);
282
if ((f->ticker->time - d->last_error_reported_time)>5000 || d->last_error_reported_time==0) {
283
d->last_error_reported_time=f->ticker->time;
284
ms_filter_notify_no_arg(f,MS_VIDEO_DECODER_DECODING_ERRORS);
289
ms_queue_put(f->outputs[0],get_as_yuvmsg(f,d,&orig));
290
if (!d->first_image_decoded) {
291
ms_filter_notify_no_arg(f,MS_VIDEO_DECODER_FIRST_IMAGE_DECODED);
292
d->first_image_decoded = TRUE;
302
static int dec_add_fmtp(MSFilter *f, void *arg){
303
DecData *d=(DecData*)f->data;
304
const char *fmtp=(const char *)arg;
306
if (fmtp_get_value(fmtp,"sprop-parameter-sets",value,sizeof(value))){
307
char * b64_sps=value;
308
char * b64_pps=strchr(value,',');
312
ms_message("Got sprop-parameter-sets : sps=%s , pps=%s",b64_sps,b64_pps);
313
d->sps=allocb(sizeof(value),0);
314
d->sps->b_wptr+=b64_decode(b64_sps,strlen(b64_sps),d->sps->b_wptr,sizeof(value));
315
d->pps=allocb(sizeof(value),0);
316
d->pps->b_wptr+=b64_decode(b64_pps,strlen(b64_pps),d->pps->b_wptr,sizeof(value));
322
static int reset_first_image(MSFilter* f, void *data) {
323
DecData *d=(DecData*)f->data;
324
d->first_image_decoded = FALSE;
328
static MSFilterMethod h264_dec_methods[]={
329
{ MS_FILTER_ADD_FMTP , dec_add_fmtp },
330
{ MS_VIDEO_DECODER_RESET_FIRST_IMAGE_NOTIFICATION, reset_first_image },
336
MSFilterDesc ms_h264_dec_desc={
339
.text="A H264 decoder based on ffmpeg project.",
340
.category=MS_FILTER_DECODER,
345
.preprocess=dec_preprocess,
346
.process=dec_process,
348
.methods=h264_dec_methods
354
MSFilterDesc ms_h264_dec_desc={
357
"A H264 decoder based on ffmpeg project.",
372
MS_FILTER_DESC_EXPORT(ms_h264_dec_desc)