source: titan/libeplayer3/output/writer/mipsel/h264.c @ 42177

Last change on this file since 42177 was 42177, checked in by obi, 5 years ago

reset libeplayer3 to v36

File size: 14.6 KB
Line 
1/*
2 * linuxdvb output/writer handling.
3 *
4 * konfetti 2010 based on linuxdvb.c code from libeplayer2
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
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.
15 *
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
19 *
20 */
21
22/* ***************************** */
23/* Includes                      */
24/* ***************************** */
25
26#include <stdio.h>
27#include <string.h>
28#include <stdlib.h>
29#include <unistd.h>
30#include <fcntl.h>
31#include <sys/types.h>
32#include <sys/stat.h>
33#include <sys/ioctl.h>
34#include <sys/uio.h>
35#include <linux/dvb/video.h>
36#include <linux/dvb/audio.h>
37#include <memory.h>
38#include <asm/types.h>
39#include <pthread.h>
40#include <errno.h>
41#include <assert.h>
42#include <stdint.h>
43#include <poll.h>
44
45#include "stm_ioctls.h"
46#include "bcm_ioctls.h"
47
48#include "common.h"
49#include "output.h"
50#include "debug.h"
51#include "misc.h"
52#include "pes.h"
53#include "writer.h"
54
55/* ***************************** */
56/* Makros/Constants              */
57/* ***************************** */
58//#define H264_DEBUG
59#ifdef H264_DEBUG
60
61static short debug_level = 0;
62
63#define h264_printf(level, fmt, x...) do { \
64if (debug_level >= level) printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
65#else
66#define h264_printf(level, fmt, x...)
67#endif
68
69#ifndef H264_SILENT
70#define h264_err(fmt, x...) do { printf("[%s:%s] " fmt, __FILE__, __FUNCTION__, ## x); } while (0)
71#else
72#define h264_err(fmt, x...)
73#endif
74
75#define IOVEC_SIZE                                      128
76
77/* ***************************** */
78/* Types                         */
79/* ***************************** */
80
81/* ***************************** */
82/* Varaibles                     */
83/* ***************************** */
84static unsigned char           Head[] = {0, 0, 0, 1};
85static int                     initialHeader = 1;
86static unsigned int            NalLengthBytes = 1;
87static unsigned char           *CodecData     = NULL;
88static unsigned int            CodecDataLen   = 0;
89static int                     avc3 = 0;
90/* ***************************** */
91/* Prototypes                    */
92/* ***************************** */
93
94/* ***************************** */
95/* MISC Functions                */
96/* ***************************** */
97
98// Please see: https://bugzilla.mozilla.org/show_bug.cgi?id=1105771
99static int32_t UpdateExtraData(uint8_t **ppExtraData, uint32_t *pExtraDataSize, uint8_t *pData, uint32_t dataSize)
100{
101    uint8_t *aExtraData = *ppExtraData;
102   
103    if (aExtraData[0] != 1 || !pData) {
104        // Not AVCC or nothing to update with.
105        return -1;
106    }
107   
108    int32_t nalsize = (aExtraData[4] & 3) + 1;
109   
110    uint8_t sps[256];
111    uint8_t spsIdx = 0;
112   
113    uint8_t numSps = 0;
114   
115    uint8_t pps[256];
116    uint8_t ppsIdx = 0;
117   
118    uint8_t numPps = 0;
119
120    if(nalsize != 4)
121    {
122        return -1;
123    }
124   
125    // Find SPS and PPS NALUs in AVCC data
126    uint8_t *d = pData;
127    while (d + 4 < pData + dataSize)
128    {
129        uint32_t nalLen = ReadUint32(d);
130       
131        uint8_t nalType = d[4] & 0x1f;
132        if (nalType == 7)
133        { /* SPS */
134       
135            // 16 bits size
136            sps[spsIdx++] = (uint8_t)(0xFF & (nalLen >> 8));
137            sps[spsIdx++] = (uint8_t)(0xFF & nalLen);
138           
139            if (spsIdx + nalLen >= sizeof(sps))
140            {
141                h264_err("SPS no free space to copy...\n");
142                return -1;
143            }
144            memcpy(&(sps[spsIdx]), d + 4, nalLen);
145            spsIdx += nalLen;
146           
147            numSps += 1;
148           
149            h264_printf(10, "SPS len[%u]...\n", nalLen);
150        }
151        else if (nalType == 8)
152        { /* PPS */
153
154            // 16 bits size
155            pps[ppsIdx++] = (uint8_t)(0xFF & (nalLen >> 8));
156            pps[ppsIdx++] = (uint8_t)(0xFF & nalLen);
157           
158            if (ppsIdx + nalLen >= sizeof(sps))
159            {
160                h264_err("PPS not free space to copy...\n");
161                return -1;
162            }
163            memcpy(&(pps[ppsIdx]), d + 4, nalLen);
164            ppsIdx += nalLen;
165           
166            numPps += 1;
167           
168            h264_printf(10, "PPS len[%u]...\n", nalLen);
169        }
170        d += 4 + nalLen;
171    }
172    uint32_t idx = 0;
173    *ppExtraData = malloc(7 + spsIdx + ppsIdx);
174    aExtraData = *ppExtraData;
175    aExtraData[idx++] = 0x1;            // version
176    aExtraData[idx++] = sps[3];         // profile
177    aExtraData[idx++] = sps[4];         // profile compat
178    aExtraData[idx++] = sps[5];         // level
179    aExtraData[idx++] = 0xff;           // nal size - 1
180   
181    aExtraData[idx++] = 0xe0 | numSps;
182    if (numSps)
183    {
184        memcpy(&(aExtraData[idx]), sps, spsIdx);
185        idx += spsIdx;
186    }
187   
188    aExtraData[idx++] = numPps;
189    if (numPps)
190    {
191        memcpy(&(aExtraData[idx]), pps, ppsIdx);
192        idx += ppsIdx;
193    }
194   
195    h264_printf(10, "aExtraData len[%u]...\n", idx);
196    *pExtraDataSize = idx;
197    return 0;
198}
199
200static int32_t PreparCodecData(unsigned char *data, unsigned int cd_len, unsigned int *NalLength)
201{
202    h264_printf(10, "H264 check codec data..!\n");
203    int32_t ret = -100;
204    if (data)
205    {
206        unsigned char tmp[2048];
207        unsigned int tmp_len = 0;
208
209        unsigned int cd_pos = 0;
210        h264_printf(10, "H264 have codec data..!\n");
211        if (cd_len > 7 && data[0] == 1)
212        {
213            unsigned short len = (data[6] << 8) | data[7];
214            if (cd_len >= (len + 8))
215            {
216                unsigned int i=0;
217                uint8_t profile_num[] = { 66, 77, 88, 100 };
218                uint8_t profile_cmp[2] = { 0x67, 0x00 };
219                const char *profile_str[] = { "baseline", "main", "extended", "high" };
220                memcpy(tmp, Head, sizeof(Head));
221                tmp_len += 4;
222                memcpy(tmp + tmp_len, data + 8, len);
223                for (i = 0; i < 4; ++i)
224                {
225                    profile_cmp[1] = profile_num[i];
226                    if (!memcmp(tmp+tmp_len, profile_cmp, 2))
227                    {
228                        uint8_t level_org = tmp[tmp_len + 3];
229                        if (level_org > 0x29)
230                        {
231                            h264_printf(10, "H264 %s profile@%d.%d patched down to 4.1!", profile_str[i], level_org / 10 , level_org % 10);
232                            tmp[tmp_len+3] = 0x29; // level 4.1
233                        }
234                        else
235                        {
236                            h264_printf(10, "H264 %s profile@%d.%d", profile_str[i], level_org / 10 , level_org % 10);
237                        }
238                        break;
239                    }
240                }
241                tmp_len += len;
242                cd_pos = 8 + len;
243                if (cd_len > (cd_pos + 2))
244                {
245                    len = (data[cd_pos + 1] << 8) | data[cd_pos + 2];
246                    cd_pos += 3;
247                    if (cd_len >= (cd_pos+len))
248                    {
249                        memcpy(tmp+tmp_len, "\x00\x00\x00\x01", 4);
250                        tmp_len += 4;
251                        memcpy(tmp+tmp_len, data+cd_pos, len);
252                        tmp_len += len;
253                       
254                        CodecData = malloc(tmp_len);
255                        memcpy(CodecData, tmp, tmp_len);
256                        CodecDataLen = tmp_len;
257                       
258                        *NalLength = (data[4] & 0x03) + 1;
259                        ret = 0;
260                    }
261                    else
262                    {
263                        h264_printf(10, "codec_data too short(4)");
264                        ret = -4;
265                    }
266                }
267                else
268                {
269                    h264_printf(10,  "codec_data too short(3)");
270                    ret = -3;
271                }
272            }
273            else
274            {
275                h264_printf(10, "codec_data too short(2)");
276                ret = -2;
277            }
278        }
279        else if (cd_len <= 7)
280        {
281            h264_printf(10, "codec_data too short(1)");
282            ret = -1;
283        }
284        else
285        {
286            h264_printf(10, "wrong avcC version %d!", data[0]);
287        }
288    }
289    else
290    {
291        *NalLength = 0;
292    }
293   
294    return ret;
295}
296
297static int reset()
298{
299    initialHeader = 1;
300    avc3 = 0;
301    return 0;
302}
303
304static int writeData(void* _call)
305{
306    WriterAVCallData_t* call = (WriterAVCallData_t*) _call;
307
308    unsigned char           PesHeader[PES_MAX_HEADER_SIZE];
309    unsigned long long int  VideoPts;
310    unsigned int            TimeDelta;
311    unsigned int            TimeScale;
312    int                     len = 0;
313    int ic = 0;
314    struct iovec iov[IOVEC_SIZE];
315    h264_printf(20, "\n");
316
317    if (call == NULL)
318    {
319        h264_err("call data is NULL...\n");
320        return 0;
321    }
322
323    TimeDelta = call->FrameRate;
324    TimeScale = call->FrameScale;
325    VideoPts  = call->Pts;
326   
327    h264_printf(20, "VideoPts %lld - %d %d\n", call->Pts, TimeDelta, TimeScale);
328
329    if ((call->data == NULL) || (call->len <= 0))
330    {
331        h264_err("NULL Data. ignoring...\n");
332        return 0;
333    }
334
335    if (call->fd < 0)
336    {
337        h264_err("file pointer < 0. ignoring ...\n");
338        return 0;
339    }
340
341    /* AnnexA */
342    if( !avc3 && ((1 < call->private_size && 0 == call->private_data[0]) ||
343        (call->len > 3) && ((call->data[0] == 0x00 && call->data[1] == 0x00 && call->data[2] == 0x00 && call->data[3] == 0x01) ||
344        (call->data[0] == 0xff && call->data[1] == 0xff && call->data[2] == 0xff && call->data[3] == 0xff))))
345    {
346        uint32_t PacketLength = 0;
347        uint32_t FakeStartCode = (call->Version << 8) | PES_VERSION_FAKE_START_CODE;
348       
349        iov[ic++].iov_base = PesHeader;
350        initialHeader = 0;
351        if (initialHeader)
352        {
353            initialHeader = 0;
354            iov[ic].iov_base  = call->private_data;
355            iov[ic++].iov_len = call->private_size;
356            PacketLength     += call->private_size;
357        }
358
359        iov[ic].iov_base = "";
360        iov[ic++].iov_len = 1;
361       
362        iov[ic].iov_base  = call->data;
363        iov[ic++].iov_len = call->len;
364        PacketLength     += call->len;
365       
366        /*Hellmaster1024: some packets will only be accepted by the player if we send one byte more than
367                          data is available. The content of this byte does not matter. It will be ignored
368                          by the player */
369//obi
370        iov[ic].iov_base = "\0";
371        iov[ic++].iov_len = 1;
372//obi (end)
373        iov[0].iov_len = InsertPesHeader(PesHeader, -1, MPEG_VIDEO_PES_START_CODE, VideoPts, FakeStartCode);
374       
375        return writev_with_retry(call->fd, iov, ic);
376    }
377    else if (!call->private_data || call->private_size < 7 || 1 != call->private_data[0])
378    {
379        h264_err("No valid private data available! [%d]\n", (int)call->private_size);
380        return 0;
381    }
382
383    uint32_t PacketLength = 0;
384   
385    ic = 0;
386    iov[ic++].iov_base = PesHeader;
387   
388    if (initialHeader)
389    {
390        if (CodecData)
391        {
392            free(CodecData);
393            CodecData = NULL;
394        }
395       
396        uint8_t  *private_data = call->private_data;
397        uint32_t  private_size = call->private_size;
398   
399        if ( PreparCodecData(private_data, private_size, &NalLengthBytes))
400        {
401            UpdateExtraData(&private_data, &private_size, call->data, call->len);
402            PreparCodecData(private_data, private_size, &NalLengthBytes);
403        }
404       
405        if (private_data != call->private_data)
406        {
407            avc3 = 1;
408            free(private_data);
409            private_data = NULL;
410        }
411       
412        if (CodecData != NULL)
413        {
414            iov[ic].iov_base  = CodecData;
415            iov[ic++].iov_len = CodecDataLen;
416            PacketLength     += CodecDataLen;
417            initialHeader = 0;
418        }
419    }
420
421    if (CodecData != NULL)
422    {
423        uint32_t pos = 0;
424        do
425        {
426            if (ic >= IOVEC_SIZE)
427            {
428                h264_err(">> Drop data due to ic overflow\n");
429                break;
430            }
431           
432            uint32_t pack_len = 0;
433            uint32_t i = 0;
434            for (i = 0; i < NalLengthBytes; i++, pos++)
435            {
436                pack_len <<= 8;
437                pack_len += call->data[pos];
438            }
439           
440            if ( (pos + pack_len) > call->len )
441            {
442                pack_len = call->len - pos;
443            }
444           
445            iov[ic].iov_base  = Head;
446            iov[ic++].iov_len = sizeof(Head);
447            PacketLength += sizeof(Head);
448           
449            iov[ic].iov_base  = call->data + pos;
450            iov[ic++].iov_len = pack_len;
451            PacketLength     += pack_len;
452   
453            pos += pack_len;
454           
455        } while ((pos + NalLengthBytes) < call->len);
456       
457        h264_printf (10, "<<<< PacketLength [%d]\n", PacketLength);
458        iov[0].iov_len = InsertPesHeader(PesHeader, -1, MPEG_VIDEO_PES_START_CODE, VideoPts, 0);
459       
460        len = writev_with_retry(call->fd, iov, ic);
461        PacketLength += iov[0].iov_len;
462        if (PacketLength != len)
463        {
464            h264_err("<<<< not all data have been written [%d/%d]\n", len, PacketLength);
465        }
466    }
467
468    h264_printf (10, "< len %d\n", len);
469    return len;
470}
471
472static int writeReverseData(void* _call)
473{
474    WriterAVCallData_t* call = (WriterAVCallData_t*) _call;
475   
476    return 0;
477}
478/* ***************************** */
479/* Writer  Definition            */
480/* ***************************** */
481
482static WriterCaps_t caps = {
483    "h264",
484    eVideo,
485    "V_MPEG4/ISO/AVC",
486    VIDEO_ENCODING_H264,
487    STREAMTYPE_MPEG4_H264,
488    CT_H264
489};
490
491struct Writer_s WriterVideoH264 = {
492    &reset,
493    &writeData,
494    &writeReverseData,
495    &caps
496};
Note: See TracBrowser for help on using the repository browser.