initial vp8 support

parent ed7f62c6
......@@ -107,7 +107,9 @@ typedef enum MSFilterId{
MS_ANDROID_DISPLAY_ID,
MS_ANDROID_VIDEO_READ_ID,
MS_ANDROID_VIDEO_WRITE_ID,
MS_TONE_DETECTOR_ID
MS_TONE_DETECTOR_ID,
MS_VP8_ENC_ID,
MS_VP8_DEC_ID
} MSFilterId;
......
......@@ -91,6 +91,10 @@ static void dec_snow_init(MSFilter *f){
dec_init(f,CODEC_ID_SNOW);
}
static void dec_vp8_init(MSFilter *f){
dec_init(f,CODEC_ID_VP8);
}
static void dec_uninit(MSFilter *f){
DecState *s=(DecState*)f->data;
if (s->av_context.codec!=NULL){
......@@ -216,6 +220,24 @@ static mblk_t * skip_rfc2429_header(mblk_t *inm){
return NULL;
}
static mblk_t * skip_draft_vp8_header(mblk_t *inm){
if (msgdsize(inm) >= 2){
unsigned char vp8_payload_desc = *(inm->b_rptr);
int payload_desc_size = 1;
/* has picture id ? */
if (vp8_payload_desc & 0b00010000) {
/* extended picture id ? */
if (inm->b_rptr[1] & 0b10000000)
payload_desc_size = 3;
else
payload_desc_size = 2;
}
inm->b_rptr += payload_desc_size;
return inm;
}else freemsg(inm);
return NULL;
}
static mblk_t * parse_snow_header(DecState *s,mblk_t *inm){
if (msgdsize(inm) >= 4){
uint32_t h = ntohl(*(uint32_t*)inm->b_rptr);
......@@ -638,6 +660,8 @@ static void dec_process_frame(MSFilter *f, mblk_t *inm){
else if (f->desc->id==MS_H263_OLD_DEC_ID) inm=skip_rfc2190_header(inm);
else if (s->codec==CODEC_ID_SNOW && s->input==NULL) inm=parse_snow_header(s,inm);
else if (s->codec==CODEC_ID_MJPEG && f->desc->id==MS_JPEG_DEC_ID) inm=read_rfc2435_header(s,inm);
else if (f->desc->id==MS_VP8_DEC_ID) inm=skip_draft_vp8_header(inm);
if (inm){
/* accumulate the video packet until we have the rtp markbit*/
if (s->input==NULL){
......@@ -902,12 +926,29 @@ MSFilterDesc ms_snow_dec_desc={
.methods= methods
};
MSFilterDesc ms_vp8_dec_desc={
.id=MS_VP8_DEC_ID,
.name="MSVp8Dec",
.text="A VP8 decoder using ffmpeg library",
.category=MS_FILTER_DECODER,
.enc_fmt="VP8-DRAFT-0-3-2",
.ninputs=1,
.noutputs=1,
.init=dec_vp8_init,
.preprocess=dec_preprocess,
.process=dec_process,
.postprocess=dec_postprocess,
.uninit=dec_uninit,
.methods= methods
};
#endif
MS_FILTER_DESC_EXPORT(ms_mpeg4_dec_desc)
MS_FILTER_DESC_EXPORT(ms_h263_dec_desc)
MS_FILTER_DESC_EXPORT(ms_h263_old_dec_desc)
MS_FILTER_DESC_EXPORT(ms_snow_dec_desc)
MS_FILTER_DESC_EXPORT(ms_vp8_dec_desc)
/* decode JPEG image with RTP/jpeg headers */
MS_FILTER_DESC_EXPORT(ms_jpeg_dec_desc)
......
......@@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "mediastreamer2/msfilter.h"
#include "mediastreamer2/msvideo.h"
#include "mediastreamer2/msticker.h"
#include "mediastreamer2/rfcxxxx_vp8.h"
#ifdef _WIN32
#include <ws2tcpip.h>
......@@ -232,6 +233,10 @@ static void enc_mjpeg_init(MSFilter *f){
enc_init(f,CODEC_ID_MJPEG);
}
static void enc_vp8_init(MSFilter *f){
enc_init(f,CODEC_ID_VP8);
}
static void prepare(EncState *s){
AVCodecContext *c=&s->av_context;
#ifdef ANDROID
......@@ -320,6 +325,11 @@ static void prepare_mpeg4(EncState *s){
c->max_b_frames=0; /*don't use b frames*/
}
static void prepare_vp8(EncState *s){
AVCodecContext *c=&s->av_context;
c->max_b_frames=0; /*don't use b frames*/
}
static void enc_uninit(MSFilter *f){
EncState *s=(EncState*)f->data;
ms_free(s);
......@@ -337,6 +347,8 @@ static void enc_preprocess(MSFilter *f){
/**/
}else if (s->codec==CODEC_ID_MJPEG){
/**/
}else if (s->codec==CODEC_ID_VP8){
prepare_vp8(s);
}else {
ms_error("Unsupported codec id %i",s->codec);
return;
......@@ -457,6 +469,65 @@ static void mpeg4_fragment_and_send(MSFilter *f,EncState *s,mblk_t *frame, uint3
mblk_set_marker_info(packet,TRUE);
}
static void vp8_fragment_and_send(MSFilter *f,EncState *s,mblk_t *frame, uint32_t timestamp){
AVCodecContext *c=&s->av_context;
uint8_t *rptr;
mblk_t *packet=NULL;
mblk_t* vp8_payload_desc = NULL;
int len;
bool_t fragmented = (frame->b_wptr-frame->b_rptr > s->mtu);
for (rptr=frame->b_rptr;rptr<frame->b_wptr;){
vp8_payload_desc = allocb(1, 0);
vp8_payload_desc->b_wptr=vp8_payload_desc->b_rptr+1;
len=MIN(s->mtu,(frame->b_wptr-rptr));
packet=dupb(frame);
packet->b_rptr=rptr;
packet->b_wptr=rptr+len;
mblk_set_timestamp_info(packet,timestamp);
mblk_set_timestamp_info(vp8_payload_desc,timestamp);
/* insert 1 byte vp8 payload descriptor */
(*vp8_payload_desc->b_rptr) = 0;
/* RSV field, always 0 */
(*vp8_payload_desc->b_rptr) &= 0b00011111;
/* I (1 if picture ID is present) */
// (*vp8_payload_desc->b_rptr) |= 0b00010000;
/* N : set to 1 if non reference frame */
if (c->coded_frame->pict_type!=FF_I_TYPE)
(*vp8_payload_desc->b_rptr) |= 0b00001000;
/* FI : partition fragmentation information */
/* (currently frame frag) */
if (fragmented) {
if (rptr == frame->b_rptr) {
/* first fragment */
(*vp8_payload_desc->b_rptr) |= 0b00000010;
} else if (rptr>=frame->b_wptr) {
/* last one */
(*vp8_payload_desc->b_rptr) |= 0b00000100;
} else {
(*vp8_payload_desc->b_rptr) |= 0b00000110;
}
} else {
//(*vp8_payload_desc->b_rptr) &= 0b11111001;
}
/* B : frame beginning */
if (rptr == frame->b_rptr) {
(*vp8_payload_desc->b_rptr) |= 0b00000001;
}
vp8_payload_desc->b_cont = packet;
ms_queue_put(f->outputs[0], vp8_payload_desc/*packet*/);
//ms_queue_put(f->outputs[0], packet);
rptr+=len;
}
/*set marker bit on last packet*/
mblk_set_marker_info(packet,TRUE);
mblk_set_marker_info(vp8_payload_desc,TRUE);
}
static void rfc4629_generate_follow_on_packets(MSFilter *f, EncState *s, mblk_t *frame, uint32_t timestamp, uint8_t *psc, uint8_t *end, bool_t last_packet){
mblk_t *packet;
int len=end-psc;
......@@ -727,6 +798,11 @@ static void split_and_send(MSFilter *f, EncState *s, mblk_t *frame){
mpeg4_fragment_and_send(f,s,frame,timestamp);
return;
}
else if (s->codec==CODEC_ID_VP8)
{
vp8_fragment_and_send(f,s,frame,timestamp);
return;
}
else if (s->codec==CODEC_ID_MJPEG)
{
mblk_t *lqt=NULL;
......@@ -792,7 +868,9 @@ static void process_frame(MSFilter *f, mblk_t *inm){
comp_buf->b_wptr+=4;
comp_buf_sz-=4;
}
error=avcodec_encode_video(c, (uint8_t*)comp_buf->b_wptr,comp_buf_sz, &pict);
if (error<=0) ms_warning("ms_AVencoder_process: error %i.",error);
else{
s->framenum++;
......@@ -1064,6 +1142,22 @@ MSFilterDesc ms_mjpeg_enc_desc={
.methods=methods
};
MSFilterDesc ms_vp8_enc_desc={
.id=MS_VP8_ENC_ID,
.name="MSVp8Enc",
.text=N_("A video VP8 encoder using ffmpeg library."),
.category=MS_FILTER_ENCODER,
.enc_fmt="VP8-DRAFT-0-3-2",
.ninputs=1, /*MS_YUV420P is assumed on this input */
.noutputs=1,
.init=enc_vp8_init,
.preprocess=enc_preprocess,
.process=enc_process,
.postprocess=enc_postprocess,
.uninit=enc_uninit,
.methods=methods
};
#endif
void __register_ffmpeg_encoders_if_possible(void){
......@@ -1080,5 +1174,9 @@ void __register_ffmpeg_encoders_if_possible(void){
{
ms_filter_register(&ms_mjpeg_enc_desc);
}
if (avcodec_find_encoder(CODEC_ID_VP8))
{
ms_filter_register(&ms_vp8_enc_desc);
}
}
......@@ -178,6 +178,8 @@ const char *usage="mediastream --local <port> --remote <ip:port> --payload <payl
"[ --rc (enable adaptive rate control)\n";
int main(int argc, char * argv[])
{
int i;
......@@ -207,6 +209,7 @@ int main(int argc, char * argv[])
rtp_profile_set_payload(&av_profile,99,&payload_type_mp4v);
rtp_profile_set_payload(&av_profile,100,&payload_type_x_snow);
rtp_profile_set_payload(&av_profile,102,&payload_type_h264);
rtp_profile_set_payload(&av_profile,103,&payload_type_vp8);
#endif
vs.width=MS_VIDEO_SIZE_CIF_W;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment