Path: blob/master/drivers/media/dvb/ttpci/av7110_ipack.c
15111 views
#include "dvb_filter.h"1#include "av7110_ipack.h"2#include <linux/string.h> /* for memcpy() */3#include <linux/vmalloc.h>456void av7110_ipack_reset(struct ipack *p)7{8p->found = 0;9p->cid = 0;10p->plength = 0;11p->flag1 = 0;12p->flag2 = 0;13p->hlength = 0;14p->mpeg = 0;15p->check = 0;16p->which = 0;17p->done = 0;18p->count = 0;19}202122int av7110_ipack_init(struct ipack *p, int size,23void (*func)(u8 *buf, int size, void *priv))24{25if (!(p->buf = vmalloc(size*sizeof(u8)))) {26printk(KERN_WARNING "Couldn't allocate memory for ipack\n");27return -ENOMEM;28}29p->size = size;30p->func = func;31p->repack_subids = 0;32av7110_ipack_reset(p);33return 0;34}353637void av7110_ipack_free(struct ipack *p)38{39vfree(p->buf);40}414243static void send_ipack(struct ipack *p)44{45int off;46struct dvb_audio_info ai;47int ac3_off = 0;48int streamid = 0;49int nframes = 0;50int f = 0;5152switch (p->mpeg) {53case 2:54if (p->count < 10)55return;56p->buf[3] = p->cid;57p->buf[4] = (u8)(((p->count - 6) & 0xff00) >> 8);58p->buf[5] = (u8)((p->count - 6) & 0x00ff);59if (p->repack_subids && p->cid == PRIVATE_STREAM1) {60off = 9 + p->buf[8];61streamid = p->buf[off];62if ((streamid & 0xf8) == 0x80) {63ai.off = 0;64ac3_off = ((p->buf[off + 2] << 8)|65p->buf[off + 3]);66if (ac3_off < p->count)67f = dvb_filter_get_ac3info(p->buf + off + 3 + ac3_off,68p->count - ac3_off, &ai, 0);69if (!f) {70nframes = (p->count - off - 3 - ac3_off) /71ai.framesize + 1;72p->buf[off + 2] = (ac3_off >> 8) & 0xff;73p->buf[off + 3] = (ac3_off) & 0xff;74p->buf[off + 1] = nframes;75ac3_off += nframes * ai.framesize - p->count;76}77}78}79p->func(p->buf, p->count, p->data);8081p->buf[6] = 0x80;82p->buf[7] = 0x00;83p->buf[8] = 0x00;84p->count = 9;85if (p->repack_subids && p->cid == PRIVATE_STREAM186&& (streamid & 0xf8) == 0x80) {87p->count += 4;88p->buf[9] = streamid;89p->buf[10] = (ac3_off >> 8) & 0xff;90p->buf[11] = (ac3_off) & 0xff;91p->buf[12] = 0;92}93break;9495case 1:96if (p->count < 8)97return;98p->buf[3] = p->cid;99p->buf[4] = (u8)(((p->count - 6) & 0xff00) >> 8);100p->buf[5] = (u8)((p->count - 6) & 0x00ff);101p->func(p->buf, p->count, p->data);102103p->buf[6] = 0x0f;104p->count = 7;105break;106}107}108109110void av7110_ipack_flush(struct ipack *p)111{112if (p->plength != MMAX_PLENGTH - 6 || p->found <= 6)113return;114p->plength = p->found - 6;115p->found = 0;116send_ipack(p);117av7110_ipack_reset(p);118}119120121static void write_ipack(struct ipack *p, const u8 *data, int count)122{123u8 headr[3] = { 0x00, 0x00, 0x01 };124125if (p->count < 6) {126memcpy(p->buf, headr, 3);127p->count = 6;128}129130if (p->count + count < p->size){131memcpy(p->buf+p->count, data, count);132p->count += count;133} else {134int rest = p->size - p->count;135memcpy(p->buf+p->count, data, rest);136p->count += rest;137send_ipack(p);138if (count - rest > 0)139write_ipack(p, data + rest, count - rest);140}141}142143144int av7110_ipack_instant_repack (const u8 *buf, int count, struct ipack *p)145{146int l;147int c = 0;148149while (c < count && (p->mpeg == 0 ||150(p->mpeg == 1 && p->found < 7) ||151(p->mpeg == 2 && p->found < 9))152&& (p->found < 5 || !p->done)) {153switch (p->found) {154case 0:155case 1:156if (buf[c] == 0x00)157p->found++;158else159p->found = 0;160c++;161break;162case 2:163if (buf[c] == 0x01)164p->found++;165else if (buf[c] == 0)166p->found = 2;167else168p->found = 0;169c++;170break;171case 3:172p->cid = 0;173switch (buf[c]) {174case PROG_STREAM_MAP:175case PRIVATE_STREAM2:176case PROG_STREAM_DIR:177case ECM_STREAM :178case EMM_STREAM :179case PADDING_STREAM :180case DSM_CC_STREAM :181case ISO13522_STREAM:182p->done = 1;183/* fall through */184case PRIVATE_STREAM1:185case VIDEO_STREAM_S ... VIDEO_STREAM_E:186case AUDIO_STREAM_S ... AUDIO_STREAM_E:187p->found++;188p->cid = buf[c];189c++;190break;191default:192p->found = 0;193break;194}195break;196197case 4:198if (count-c > 1) {199p->plen[0] = buf[c];200c++;201p->plen[1] = buf[c];202c++;203p->found += 2;204p->plength = (p->plen[0] << 8) | p->plen[1];205} else {206p->plen[0] = buf[c];207p->found++;208return count;209}210break;211case 5:212p->plen[1] = buf[c];213c++;214p->found++;215p->plength = (p->plen[0] << 8) | p->plen[1];216break;217case 6:218if (!p->done) {219p->flag1 = buf[c];220c++;221p->found++;222if ((p->flag1 & 0xc0) == 0x80)223p->mpeg = 2;224else {225p->hlength = 0;226p->which = 0;227p->mpeg = 1;228p->flag2 = 0;229}230}231break;232233case 7:234if (!p->done && p->mpeg == 2) {235p->flag2 = buf[c];236c++;237p->found++;238}239break;240241case 8:242if (!p->done && p->mpeg == 2) {243p->hlength = buf[c];244c++;245p->found++;246}247break;248}249}250251if (c == count)252return count;253254if (!p->plength)255p->plength = MMAX_PLENGTH - 6;256257if (p->done || ((p->mpeg == 2 && p->found >= 9) ||258(p->mpeg == 1 && p->found >= 7))) {259switch (p->cid) {260case AUDIO_STREAM_S ... AUDIO_STREAM_E:261case VIDEO_STREAM_S ... VIDEO_STREAM_E:262case PRIVATE_STREAM1:263if (p->mpeg == 2 && p->found == 9) {264write_ipack(p, &p->flag1, 1);265write_ipack(p, &p->flag2, 1);266write_ipack(p, &p->hlength, 1);267}268269if (p->mpeg == 1 && p->found == 7)270write_ipack(p, &p->flag1, 1);271272if (p->mpeg == 2 && (p->flag2 & PTS_ONLY) &&273p->found < 14) {274while (c < count && p->found < 14) {275p->pts[p->found - 9] = buf[c];276write_ipack(p, buf + c, 1);277c++;278p->found++;279}280if (c == count)281return count;282}283284if (p->mpeg == 1 && p->which < 2000) {285286if (p->found == 7) {287p->check = p->flag1;288p->hlength = 1;289}290291while (!p->which && c < count &&292p->check == 0xff){293p->check = buf[c];294write_ipack(p, buf + c, 1);295c++;296p->found++;297p->hlength++;298}299300if (c == count)301return count;302303if ((p->check & 0xc0) == 0x40 && !p->which) {304p->check = buf[c];305write_ipack(p, buf + c, 1);306c++;307p->found++;308p->hlength++;309310p->which = 1;311if (c == count)312return count;313p->check = buf[c];314write_ipack(p, buf + c, 1);315c++;316p->found++;317p->hlength++;318p->which = 2;319if (c == count)320return count;321}322323if (p->which == 1) {324p->check = buf[c];325write_ipack(p, buf + c, 1);326c++;327p->found++;328p->hlength++;329p->which = 2;330if (c == count)331return count;332}333334if ((p->check & 0x30) && p->check != 0xff) {335p->flag2 = (p->check & 0xf0) << 2;336p->pts[0] = p->check;337p->which = 3;338}339340if (c == count)341return count;342if (p->which > 2){343if ((p->flag2 & PTS_DTS_FLAGS) == PTS_ONLY) {344while (c < count && p->which < 7) {345p->pts[p->which - 2] = buf[c];346write_ipack(p, buf + c, 1);347c++;348p->found++;349p->which++;350p->hlength++;351}352if (c == count)353return count;354} else if ((p->flag2 & PTS_DTS_FLAGS) == PTS_DTS) {355while (c < count && p->which < 12) {356if (p->which < 7)357p->pts[p->which - 2] = buf[c];358write_ipack(p, buf + c, 1);359c++;360p->found++;361p->which++;362p->hlength++;363}364if (c == count)365return count;366}367p->which = 2000;368}369370}371372while (c < count && p->found < p->plength + 6) {373l = count - c;374if (l + p->found > p->plength + 6)375l = p->plength + 6 - p->found;376write_ipack(p, buf + c, l);377p->found += l;378c += l;379}380break;381}382383384if (p->done) {385if (p->found + count - c < p->plength + 6) {386p->found += count - c;387c = count;388} else {389c += p->plength + 6 - p->found;390p->found = p->plength + 6;391}392}393394if (p->plength && p->found == p->plength + 6) {395send_ipack(p);396av7110_ipack_reset(p);397if (c < count)398av7110_ipack_instant_repack(buf + c, count - c, p);399}400}401return count;402}403404405