int main(int argc, char **argv) { codec_register_all(); struct codec_packet pkt; struct codec_frame frame; // decoder test struct codec_para para; para.media_format = CODEC_MEDIA_FORMAT_H264; para.is_encoder = 0; para.media_type = CODEC_MEDIA_TYPE_VIDEO; para.width = 1280; para.height = 720; struct codec_context *codec = codec_create(¶); codec_destroy(codec); // video encoder test memset(¶, 0, sizeof(struct codec_para)); para.media_format = CODEC_MEDIA_FORMAT_H264; para.is_encoder = 1; para.media_type = CODEC_MEDIA_TYPE_VIDEO; para.width = 1280; para.height = 720; codec = codec_create(¶); pkt.data = (uint8_t *)malloc(1280 * 720 * 4); frame.key = 1; frame.data = (uint8_t *)malloc(1280 * 720 * 4); memset(frame.data, 256, 1000); codec_encode_frame(codec, &pkt, &frame); codec_destroy(codec); free(pkt.data); free(frame.data); // audio Encoder test memset(¶, 0, sizeof(struct codec_para)); para.media_format = CODEC_MEDIA_FORMAT_AAC; para.is_encoder = 1; para.media_type = CODEC_MEDIA_TYPE_AUDIO; para.samplerate = 44100; para.channels = 2; codec = codec_create(¶); pkt.data = (uint8_t *)malloc(1280 * 720 * 4); pkt.size = 1280 * 720 * 4; frame.key = 1; frame.data = (uint8_t *)malloc(1280 * 720 * 4); frame.size = 44100*2; frame.nb_samples = 44100; codec_encode_frame(codec, &pkt, &frame); codec_destroy(codec); free(pkt.data); free(frame.data); return 0; }
void xiph_destroy (demux_t *demux, void *data) { rtp_xiph_t *self = (rtp_xiph_t *)data; // sunqueen modify if (!data) return; if (self->block) { self->block->i_flags |= BLOCK_FLAG_CORRUPTED; codec_decode (demux, self->id, self->block); } codec_destroy (demux, self->id); free (self); }
void xiph_decode (demux_t *demux, void *data, block_t *block) { rtp_xiph_t *self = (rtp_xiph_t *)data; // sunqueen modify if (!data || block->i_buffer < 4) goto drop; /* 32-bits RTP header (§2.2) */ uint32_t ident = GetDWBE (block->p_buffer); block->i_buffer -= 4; block->p_buffer += 4; unsigned fragtype = (ident >> 6) & 3; unsigned datatype = (ident >> 4) & 3; unsigned pkts = (ident) & 15; ident >>= 8; /* RTP defragmentation */ if (self->block && (block->i_flags & BLOCK_FLAG_DISCONTINUITY)) { /* Screwed! discontinuity within a fragmented packet */ msg_Warn (demux, self->vorbis ? "discontinuity in fragmented Vorbis packet" : "discontinuity in fragmented Theora packet"); block_Release (self->block); self->block = NULL; } if (fragtype <= 1) { if (self->block) /* Invalid first fragment */ { block_Release (self->block); self->block = NULL; } } else { if (!self->block) goto drop; /* Invalid non-first fragment */ } if (fragtype > 0) { /* Fragment */ if (pkts > 0 || block->i_buffer < 2) goto drop; size_t fraglen = GetWBE (block->p_buffer); if (block->i_buffer < (fraglen + 2)) goto drop; /* Invalid payload length */ block->i_buffer = fraglen; if (fragtype == 1)/* Keep first fragment */ { block->i_buffer += 2; self->block = block; } else { /* Append non-first fragment */ size_t len = self->block->i_buffer; self->block = block_Realloc (self->block, 0, len + fraglen); if (!self->block) { block_Release (block); return; } memcpy (self->block->p_buffer + len, block->p_buffer + 2, fraglen); block_Release (block); } if (fragtype < 3) return; /* Non-last fragment */ /* Last fragment reached, process it */ block = self->block; self->block = NULL; SetWBE (block->p_buffer, block->i_buffer - 2); pkts = 1; } /* RTP payload packets processing */ while (pkts > 0) { if (block->i_buffer < 2) goto drop; size_t len = GetWBE (block->p_buffer); block->i_buffer -= 2; block->p_buffer += 2; if (block->i_buffer < len) goto drop; switch (datatype) { case 0: /* Raw payload */ { if (self->ident != ident) { msg_Warn (demux, self->vorbis ? "ignoring raw Vorbis payload without configuration" : "ignoring raw Theora payload without configuration"); break; } block_t *raw = block_Alloc (len); memcpy (raw->p_buffer, block->p_buffer, len); raw->i_pts = block->i_pts; /* FIXME: what about pkts > 1 */ codec_decode (demux, self->id, raw); break; } case 1: /* Packed configuration frame (§3.1.1) */ { if (self->ident == ident) break; /* Ignore config retransmission */ void *extv; ssize_t extc = xiph_header (&extv, block->p_buffer, len); if (extc < 0) break; es_format_t fmt; es_format_Init (&fmt, self->vorbis ? AUDIO_ES : VIDEO_ES, self->vorbis ? VLC_CODEC_VORBIS : VLC_CODEC_THEORA); fmt.p_extra = extv; fmt.i_extra = extc; codec_destroy (demux, self->id); msg_Dbg (demux, self->vorbis ? "Vorbis packed configuration received (%06"PRIx32")" : "Theora packed configuration received (%06"PRIx32")", ident); self->ident = ident; self->id = (es_out_id_t *)codec_init (demux, &fmt); // sunqueen modify break; } } block->i_buffer -= len; block->p_buffer += len; pkts--; } drop: block_Release (block); }
static void iaxc_handle_connect(struct iax_event * e) { #ifdef USE_VIDEO int video_format_capability; int video_format_preferred; #endif int video_format = 0; int format = 0; int callno; callno = iaxc_first_free_call(); if ( callno < 0 ) { iaxci_usermsg(IAXC_STATUS, "%i \n Incoming Call, but no appearances", callno); // XXX Reject this call!, or just ignore? //iax_reject(e->session, "Too many calls, we're busy!"); iax_accept(e->session, audio_format_preferred & e->ies.capability); iax_busy(e->session); return; } /* negotiate codec */ /* first, try _their_ preferred format */ format = audio_format_capability & e->ies.format; if ( !format ) { /* then, try our preferred format */ format = audio_format_preferred & e->ies.capability; } if ( !format ) { /* finally, see if we have one in common */ format = audio_format_capability & e->ies.capability; /* now choose amongst these, if we got one */ if ( format ) { format = iaxc_choose_codec(format); } } if ( !format ) { iax_reject(e->session, "Could not negotiate common codec"); return; } #ifdef USE_VIDEO iaxc_video_format_get_cap(&video_format_preferred, &video_format_capability); /* first, see if they even want video */ video_format = (e->ies.format & IAXC_VIDEO_FORMAT_MASK); if ( video_format ) { /* next, try _their_ preferred format */ video_format &= video_format_capability; if ( !video_format ) { /* then, try our preferred format */ video_format = video_format_preferred & (e->ies.capability & IAXC_VIDEO_FORMAT_MASK); } if ( !video_format ) { /* finally, see if we have one in common */ video_format = video_format_capability & (e->ies.capability & IAXC_VIDEO_FORMAT_MASK); /* now choose amongst these, if we got one */ if ( video_format ) { video_format = iaxc_choose_codec(video_format); } } /* All video negotiations failed, then warn */ if ( !video_format ) { iaxci_usermsg(IAXC_NOTICE, "Notice: could not negotiate common video codec"); iaxci_usermsg(IAXC_NOTICE, "Notice: switching to audio-only call"); } } #endif /* USE_VIDEO */ calls[callno].vformat = video_format; calls[callno].format = format; if ( e->ies.called_number ) strncpy(calls[callno].local, e->ies.called_number, IAXC_EVENT_BUFSIZ); else strncpy(calls[callno].local, "unknown", IAXC_EVENT_BUFSIZ); if ( e->ies.called_context ) strncpy(calls[callno].local_context, e->ies.called_context, IAXC_EVENT_BUFSIZ); else strncpy(calls[callno].local_context, "", IAXC_EVENT_BUFSIZ); if ( e->ies.calling_number ) strncpy(calls[callno].remote, e->ies.calling_number, IAXC_EVENT_BUFSIZ); else strncpy(calls[callno].remote, "unknown", IAXC_EVENT_BUFSIZ); if ( e->ies.calling_name ) strncpy(calls[callno].remote_name, e->ies.calling_name, IAXC_EVENT_BUFSIZ); else strncpy(calls[callno].remote_name, "unknown", IAXC_EVENT_BUFSIZ); iaxc_note_activity(callno); iaxci_usermsg(IAXC_STATUS, "Call from (%s)", calls[callno].remote); codec_destroy( callno ); calls[callno].session = e->session; calls[callno].state = IAXC_CALL_STATE_ACTIVE|IAXC_CALL_STATE_RINGING; iax_accept(calls[callno].session, format | video_format); iax_ring_announce(calls[callno].session); iaxci_do_state_callback(callno); iaxci_usermsg(IAXC_STATUS, "Incoming call on line %d", callno); }
EXPORT int iaxc_call_ex(const char *num, const char* callerid_name, const char* callerid_number, int video) { int video_format_capability = 0; int video_format_preferred = 0; int callNo = -1; struct iax_session *newsession; char *ext = strstr(num, "/"); get_iaxc_lock(); // if no call is selected, get a new appearance if ( selected_call < 0 ) { callNo = iaxc_first_free_call(); } else { // use selected call if not active, otherwise, get a new appearance if ( calls[selected_call].state & IAXC_CALL_STATE_ACTIVE ) { callNo = iaxc_first_free_call(); } else { callNo = selected_call; } } if ( callNo < 0 ) { iaxci_usermsg(IAXC_STATUS, "No free call appearances"); goto iaxc_call_bail; } newsession = iax_session_new(); if ( !newsession ) { iaxci_usermsg(IAXC_ERROR, "Can't make new session"); goto iaxc_call_bail; } calls[callNo].session = newsession; codec_destroy( callNo ); if ( ext ) { strncpy(calls[callNo].remote_name, num, IAXC_EVENT_BUFSIZ); strncpy(calls[callNo].remote, ++ext, IAXC_EVENT_BUFSIZ); } else { strncpy(calls[callNo].remote_name, num, IAXC_EVENT_BUFSIZ); strncpy(calls[callNo].remote, "" , IAXC_EVENT_BUFSIZ); } if ( callerid_number != NULL ) strncpy(calls[callNo].callerid_number, callerid_number, IAXC_EVENT_BUFSIZ); if ( callerid_name != NULL ) strncpy(calls[callNo].callerid_name, callerid_name, IAXC_EVENT_BUFSIZ); strncpy(calls[callNo].local , calls[callNo].callerid_name, IAXC_EVENT_BUFSIZ); strncpy(calls[callNo].local_context, "default", IAXC_EVENT_BUFSIZ); calls[callNo].state = IAXC_CALL_STATE_ACTIVE | IAXC_CALL_STATE_OUTGOING; /* reset activity and ping "timers" */ iaxc_note_activity(callNo); calls[callNo].last_ping = calls[callNo].last_activity; #ifdef USE_VIDEO if ( video ) iaxc_video_format_get_cap(&video_format_preferred, &video_format_capability); #endif iaxci_usermsg(IAXC_NOTICE, "Originating an %s call", video_format_preferred ? "audio+video" : "audio only"); iax_call(calls[callNo].session, calls[callNo].callerid_number, calls[callNo].callerid_name, num, NULL, 0, audio_format_preferred | video_format_preferred, audio_format_capability | video_format_capability); // does state stuff also iaxc_select_call(callNo); iaxc_call_bail: put_iaxc_lock(); return callNo; }
EXPORT int iaxc_call_ex(const char *num, const char* callerid_name, const char* callerid_number, int video) { int video_format_capability = 0; int video_format_preferred = 0; int callNo = -1; struct iax_session *newsession; char *ext = strstr(num, "/"); get_iaxc_lock(); // if no call is selected, get a new appearance if ( selected_call < 0 ) { callNo = iaxc_first_free_call(); } else { // use selected call if not active, otherwise, get a new appearance if ( calls[selected_call].state & IAXC_CALL_STATE_ACTIVE ) { callNo = iaxc_first_free_call(); } else { callNo = selected_call; } } if ( callNo < 0 ) { iaxci_usermsg(IAXC_STATUS, "No free call appearances"); goto iaxc_call_bail; } newsession = iax_session_new(); if ( !newsession ) { iaxci_usermsg(IAXC_ERROR, "Can't make new session"); goto iaxc_call_bail; } calls[callNo].session = newsession; codec_destroy( callNo ); /* When the ACCEPT comes back from the other-end, these formats * are set. Whether the format is set or not determines whether * we are in the Linked state (see the iax2 rfc). * These will have already been cleared by iaxc_clear_call(), * but we reset them anyway just to be pedantic. */ calls[callNo].format = 0; calls[callNo].vformat = 0; if ( ext ) { strncpy(calls[callNo].remote_name, num, IAXC_EVENT_BUFSIZ); strncpy(calls[callNo].remote, ++ext, IAXC_EVENT_BUFSIZ); } else { strncpy(calls[callNo].remote_name, num, IAXC_EVENT_BUFSIZ); strncpy(calls[callNo].remote, "" , IAXC_EVENT_BUFSIZ); } if ( callerid_number != NULL ) strncpy(calls[callNo].callerid_number, callerid_number, IAXC_EVENT_BUFSIZ); if ( callerid_name != NULL ) strncpy(calls[callNo].callerid_name, callerid_name, IAXC_EVENT_BUFSIZ); strncpy(calls[callNo].local , calls[callNo].callerid_name, IAXC_EVENT_BUFSIZ); strncpy(calls[callNo].local_context, "default", IAXC_EVENT_BUFSIZ); calls[callNo].state = IAXC_CALL_STATE_OUTGOING; /* reset activity and ping "timers" */ iaxc_note_activity(callNo); calls[callNo].last_ping = calls[callNo].last_activity; #ifdef USE_VIDEO if ( video ) iaxc_video_format_get_cap(&video_format_preferred, &video_format_capability); #endif iaxci_usermsg(IAXC_NOTICE, "Originating an %s call", video_format_preferred ? "audio+video" : "audio only"); iax_call(calls[callNo].session, calls[callNo].callerid_number, calls[callNo].callerid_name, num, NULL, 0, audio_format_preferred | video_format_preferred, audio_format_capability | video_format_capability); // does state stuff also iaxc_select_call(callNo); iaxc_call_bail: put_iaxc_lock(); return callNo; }