📄 frameread.c
字号:
/* frameread.c - frameread */#include <syn.h>#include <util.h>#include <strings.h>#include <stdlib.h>#include <unistd.h>#include <frame.h>#include <errno.h>#include <util.h>#include <limits.h>#define DEBUG(x)#include <stdio.h>/*------------------------------------------------------------------------ * frameread - read a single frame (times number of channles) from stream * Notes: frameread implicitly begins at "now". * Buflen is in bytes. * Time gives the local time of the first sample in the data. On * some errors, time gives the time of next available data. Its * initial value has no meaning. * Tsout gives the media timestamp of the beginning of the data. * Its initial value has no meaning. It has meaning only on * success. * On success, frameread returns the number of bytes copied. * Frames must be of constant size and duration. * Frameread copies extra per-packet headers (e.g., as described * in RFC 2250) as determined by pparam->fr_dataoffsetfcn. * Frameread will re-assemble fragmented frames. If fragmentation * is used, the stream can only be monaureal by the constraints * laid out in RFC 1890. Only the extra headers in the first * fragment of a fragmented frame are returned. The length of * the buffer for extraheaders is passed in by reference and on * return contains the number of bytes copied into the buffer. * All fragments from the same frame must have the same timestamp, * and must arrive sequentially. * When a packet contains a fraction of a frame, it may contain * no other frames or parts thereof. *------------------------------------------------------------------------ */intframeread(struct synsession *pssn, struct synstream *psstm, struct timespec *time, mediatime_t *tsout, char *buf, int buflen, char *extraheaderbuf, int *extraheaderbuflen, bool *mark){ struct frameparam *pparam; struct timespec now; struct rtp *prtp; struct rtpln *pln; mediatime_t mnow, ts, readfrom, frameduration; bool block, flush, aligned; int bytesleft, rv, dataoffset, chan, framelen; char *pframe; pparam = (struct frameparam *) psstm->sstm_parameters; block = (psstm->sstm_readflags & SYN_READ_BLOCK) != 0; flush = (psstm->sstm_readflags & SYN_READ_FLUSH) != 0; bzero(time, sizeof(struct timespec)); *tsout = 0; while (TRUE) { /* * Get next packet. */ if ((rv = synreadnextpacket(pssn, psstm, &pln)) < 0) return rv; prtp = &pln->rln_rtp; pframe = NULL; /* * Get length (bytes) of any per-packet headers */ dataoffset = pparam->fp_dataoffset(prtp, pln->rln_len); if (dataoffset == ERROR) { bufpoolfreebuf(pln); continue; } bytesleft = pln->rln_len - RTP_HEADER_LEN(prtp) - dataoffset; ts = prtp->rtp_time; /* * Obtain current time and convert to media time */ clock_gettime(CLOCK_REALTIME, &now); mnow = timeflatten(timesub(now, psstm->sstm_clkx), psstm->sstm_clkrt) + psstm->sstm_clky; readfrom = (flush == TRUE ? tsmax(mnow, psstm->sstm_lastread) : psstm->sstm_lastread); /* * Find first frame that is 'current' */ aligned = pparam->fp_framealigned(prtp, pln->rln_len); if (aligned == (bool) ERROR) { bufpoolfreebuf(pln); continue; } if (aligned == TRUE) { pframe = RTP_DATA(prtp) + dataoffset; frameduration = pparam->fp_frameduration(pframe, bytesleft); if (frameduration == ERROR) { bufpoolfreebuf(pln); continue; } while(!tsgt(ts + frameduration, readfrom)) { ts += frameduration; /* * Advance past all frames at this time (1 per channel). */ for (chan = 0; chan < pparam->fp_channels; chan++) { framelen = pparam->fp_framelength(pframe, bytesleft); if (framelen == ERROR) { bytesleft = 0; break; /* from for */ } pframe += framelen; bytesleft -= framelen; if (bytesleft <= 0) break; /* from for */ } /* for */ if (bytesleft <= 0) break; /* from inner while */ frameduration = pparam->fp_frameduration(pframe, bytesleft); if (frameduration == ERROR) { bytesleft = 0; break; /* from inner while */ } } /* while(ts + frameduration <= readfrom) */ /* * Check for no bytes left */ if (bytesleft <= 0) { bufpoolfreebuf(pln); continue; /* in outter while */ } } /* * Check if the data is too new to return */ if ((rv = synreadwait(pssn, psstm, pln, ts, now, mnow, time)) < 0) return rv; else if (rv == SYN_CONTINUE) continue; /* * We are now committed to this frame. * Decide if it is a full frame or fragment of a frame. */ if (pframe != NULL) { framelen = pparam->fp_framelength(pframe, bytesleft); if (framelen == ERROR) { bufpoolfreebuf(pln); return ERROR; } } if (aligned && bytesleft >= framelen) { /* * Set mark true if mark bit set AND frame is first in packet. */ *mark = prtp->rtp_mark && ((char *) pframe == (char *) prtp + dataoffset); rv = framereadnonfragmented(pssn, psstm, time, tsout, buf, buflen, extraheaderbuf, extraheaderbuflen, pln, pframe, ts, frameduration, bytesleft); } else { /* * Reinsert the packet into the queue * and invoke framereadfragmented to reassemble the frame. */ rtpqinsert(pssn->ssn_session, psstm->sstm_ssrc, pln); rv = framereadfragmented(pssn, psstm, time, tsout, buf, buflen, extraheaderbuf, extraheaderbuflen, mark, ts); } if (rv != ERROR) return rv; } /* outter while */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -