OVMS3-idf/examples/09_a2dp/components/EspAudio/player/M3u8.c
wangmengyang 0ad3017df7 component/bt: A2DP code original in example project moved to component/bt directory;
1. move btif and A2DP source code from project directory to bluetooth directory;
2. some updates of audio source code;
2016-12-26 17:40:28 +08:00

318 lines
8.9 KiB
C

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "inc/M3u8.h"
static int read_line_from_m3u8_info(char *m3u8_info, char *line_buffer, int buffer_size);
static int m3u8_info_eof();
static int parseSegFromUrl(M3u8Segment* tsp);
static char * strdupmy(const char *s);
unsigned int length;
unsigned int offset;
//////////////////////////////////////////////////////////////////////////////////////
char* trim_str(char *str)
{
char* tmp = str;
while (*str++ != '\r') {
if (*str == '\0' || *str == '\n') {
break;
}
}
*str = '\0';
return tmp;
}
// Must to be free memory
static char * strdupmy(const char *s)
{
size_t len = strlen(s) + 1;
void *new = malloc(len);
if (new == NULL)
return NULL;
return (char *)memcpy(new, s, len);
}
char* split_url(char* url, char* seg_path, char* seg_name)
{
char* temp1;
char rateStr[10] = {0};
int len = strlen(url);
while (url) {
temp1 = strrchr(url, '/');
if (temp1 == NULL) {
printf("ERR:strrchr=NULL,%s,%d\n", __FUNCTION__, __LINE__);
return NULL;
}
temp1 += 1;
strncpy(seg_path, url, temp1 - url);
strncpy(seg_name, temp1, len - (temp1 - url));
return seg_path;
}
return NULL;
}
int is_blank(char *str)
{
if (0 == strlen(str))
return 1;
else
return 0;
}
static int read_line_from_m3u8_info(char *m3u8_info, char *line_buffer, int buffer_size)
{
int start;
int end = -1;
char cur_char = '\0';
int copy_size;
start = offset;
while (offset < length) {
cur_char = m3u8_info[offset];
if (cur_char == '\r' || cur_char == '\n') {
end = offset;
offset++;
break;
}
offset++;
}
if (end == -1) {
end = length;
}
if (cur_char == '\r') {
offset++;
}
memset(line_buffer, 0, buffer_size);
copy_size = end - start;
if (copy_size > buffer_size - 1) {
copy_size = buffer_size - 1;
}
strncpy(line_buffer, m3u8_info + start, copy_size);
return 1;
}
static int m3u8_info_eof()
{
if (offset >= length) {
return 1;
} else {
return 0;
}
}
int parseSegFromUrl(M3u8Segment* tsp)
{
int len = strlen(tsp->url);
int ret = -1;
char *segment_path = (char*)malloc(len);
char *segment_name = (char*)malloc(len);
if ((segment_path == NULL) | (segment_name == NULL)) {
goto SAVEEXIT;
}
memset(segment_path, 0, len);
memset(segment_name, 0, len);
split_url(tsp->url, segment_path, segment_name);
//http://live.xmcdn.com/192.168.3.134/live/12/24/160411_000003_15f9.ts
//http://live.xmcdn.com/192.168.3.134/live/75/24/160413_082919_12b0.aac
char* temp1 = strchr(segment_name, '.');
char* temp2 = strrchr(segment_name, '_');
if ((temp1 == NULL) | (temp2 == NULL)) {
printf("ERR:strrchr=NULL,%s,%d\n", __FUNCTION__, __LINE__);
goto SAVEEXIT;
}
*temp1 = '\0';
temp1++;
if (strncmp(temp1, "aac", 3) == 0) {
tsp->fmt = AUDIOFMT_AAC;
} else if (strncmp(temp1, "ts", 3) == 0) {
tsp->fmt = AUDIOFMT_TS;
} else {
tsp->fmt = AUDIOFMT_UNKNOWN;
}
///subSeq
temp2++;
tsp->seq.sub = strtoul(temp2, 0, 16);
////mainSeq
temp2--;
*temp2 = '\0';
temp1 = strrchr(segment_name, '_');
if (temp1 == NULL) {
printf("ERR:strrchr=NULL,%s,%d\n", __FUNCTION__, __LINE__);
goto SAVEEXIT;
}
temp1++;
tsp->seq.main = strtoul(temp1, 0, 16);
///
temp2 = strchr(segment_name, '_');
if (temp2 == NULL) {
printf("ERR:strchr=NULL,%s,%d\n", __FUNCTION__, __LINE__);
goto SAVEEXIT;
}
*temp2 = '\0';
tsp->seq.date = strtoul(segment_name, 0, 16);
temp1 = strrchr(segment_path, '/');
if (temp1 == NULL) {
printf("ERR:strrchr=NULL,%s,%d\n", __FUNCTION__, __LINE__);
goto SAVEEXIT;
}
*temp1 = '\0';
temp1 = strrchr(segment_path, '/');
if (temp1 == NULL) {
printf("ERR:strrchr=NULL,%s,%d\n", __FUNCTION__, __LINE__);
goto SAVEEXIT;
}
temp1++;
tsp->rate = atoi(temp1);
ret = 0;
SAVEEXIT:
if (segment_path) {
free(segment_path);
}
if (segment_name) {
free(segment_name);
}
return ret;
}
#define ONE_LINE_SIZE 1024
M3u8Info *m3u8Parser(char *m3u8Str, M3u8Info* m3u8)
{
int has_segment = 0;
if (NULL == m3u8) {
printf("malloc for M3u8Info failed.");
return NULL;
}
char *line = malloc(ONE_LINE_SIZE);
if (NULL == line) {
printf("zalloc for line failed.");
return NULL;
}
memset(line, 0, ONE_LINE_SIZE);
memset(m3u8, 0, sizeof(M3u8Info));
length = strlen(m3u8Str);
offset = 0;
while (!m3u8_info_eof()) {
int result = 0;
char *str = NULL;
if (m3u8->segCount >= MAX_SEGMENT_COUNT) {
printf("segCount >= MAX_SEGMENT_COUNT[%d].", MAX_SEGMENT_COUNT);
break;
}
result = read_line_from_m3u8_info(m3u8Str, line, ONE_LINE_SIZE);
if (!result) {
printf("ERR:read line error from m3u8 info.");
if (line) free(line);
return NULL;
}
if (is_blank(line)) {
continue;
}
str = trim_str(line);
if (has_segment) {
int size = strlen(str) + 1;
m3u8->segList[m3u8->segCount].seq.sub = m3u8->mediaSeq + m3u8->segCount;
// m3u8->segList[m3u8->segCount - 1].url = (char *)malloc(size);
memset(m3u8->segList[m3u8->segCount].url, 0, size);
strcpy(m3u8->segList[m3u8->segCount].url, str);
parseSegFromUrl(&m3u8->segList[m3u8->segCount]);
has_segment = 0;
m3u8->segCount++;
} else {
if (0 == strncmp(str, "#EXTM3U", strlen("#EXTM3U"))) {
} else if (0 == strncmp(str, "#EXT-X-VERSION:", strlen("#EXT-X-VERSION:"))) {
} else if (0 == strncmp(str, "#EXT-X-ALLOW-CACHE:", strlen("#EXT-X-ALLOW-CACHE:"))) {
} else if (0 == strncmp(str, "#EXT-X-TARGETDURATION:", strlen("#EXT-X-TARGETDURATION:"))) {
char *str_duration = str + strlen("#EXT-X-TARGETDURATION:");
m3u8->targetDuration = atoi(trim_str(str_duration));
// printf("Get the TARGETDURATION=%d\n", m3u8->targetDuration);
} else if (0 == strncmp(str, "#EXT-X-MEDIA-SEQUENCE:", strlen("#EXT-X-MEDIA-SEQUENCE:"))) {
char *str_sequence = str + strlen("#EXT-X-MEDIA-SEQUENCE:");
m3u8->mediaSeq = atol(trim_str(str_sequence));
// printf("Get the MEDIA-SEQUENCE=%d\n", m3u8->mediaSeq);
} else if (0 == strncmp(str, "#EXTINF:", strlen("#EXTINF:"))) {
char *str_segment_duration = NULL;
int i = 0;
has_segment = 1;
str_segment_duration = str + strlen("#EXTINF:");
while (str_segment_duration[i] != 0) {
if ((str_segment_duration[i] < '0') || (str_segment_duration[i] > '9')) {
str_segment_duration[i] = 0;
break;
}
i++;
}
m3u8->segList[m3u8->segCount].duration = atoi(str_segment_duration);
} else if (0 == strncmp(str, "#EXT-X-DISCONTINUITY", strlen("#EXT-X-DISCONTINUITY"))) {
} else if (0 == strncmp(str, "#EXT-X-ENDLIST", strlen("#EXT-X-ENDLIST"))) {
} else {
printf("unknown line: %s.", str);
}
}
}
if (line) free(line);
return m3u8;
}
uint8_t m3u8CheckValid(const M3u8Seq* new, const M3u8Seq* pre)
{
if (pre->date < new->date) {
return 1;
} else if (pre->date == new->date) {
if (pre->main < new->main) {
return 1;
} else if (pre->main == new->main) {
if ((pre->sub & 0x0000FFFF) < (new->sub & 0x0000FFFF)) {
return 1;
} else {
return 0;
}
} else {
return 0;
}
} else {
return 0;
}
}
void m3u8Destroy(M3u8Info *m3u8)
{
int i = 0;
if (m3u8 == NULL) {
return;
}
free(m3u8);
}
int m3u8_test(char* pStr)
{
//char *m3u8Str = "#EXTM3U\n"
// "#EXT-X-TARGETDURATION:8\n"
// "#EXT-X-MEDIA-SEQUENCE:92595\n"
// "#EXTINF:8,\n"
// "20121120T182851-04-92595.ts\n"
// "#EXTINF:8,\n"
// "20121120T182851-04-92596.ts\n"
// "#EXTINF:8,\n"
// "20121120T182851-04-92597.ts\n"
// "#EXTINF:8,\n"
// "20121120T182851-04-92598.ts\n";
for (int i = 0; i < 10000; i++) {
// M3u8Info *m3u8 = m3u8Parser(pStr, m3u8);
// m3u8Destroy(m3u8);
}
return 1;
}