muxer_mpeg.c
来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 2,496 行 · 第 1/5 页
C
2,496 行
if(spriv->framebuf[idx].buffer == NULL) { mp_msg(MSGT_MUXER, MSGL_FATAL, "Couldn't realloc frame buffer(frame), abort\n"); return -1; } spriv->framebuf[idx].alloc_size = spriv->framebuf[idx].size + len; } memcpy(&(spriv->framebuf[idx].buffer[spriv->framebuf[idx].size]), ptr, len); spriv->framebuf[idx].size += len; spriv->framebuf[idx].pos = 0; spriv->framebuf[idx].type = pt; spriv->framebuf[idx].idur = idur; spriv->framebuf[idx].dts = dts; spriv->framebuf[idx].pts = pts; spriv->framebuf_used++; mp_msg(MSGT_MUXER, MSGL_DBG2, "\r\nAdded frame, size: %u, idur: %"PRIu64", dts: %"PRIu64", pts: %"PRIu64", used: %u\r\n", len, idur, dts, pts, spriv->framebuf_used); return idx;}static int analyze_mpa(muxer_stream_t *s){ int i = 0, len, max, chans, srate, spf, layer; int score[4] = {0, 0, 0, 0}; while(i < s->b_buffer_len + 3) { if(s->b_buffer[i] == 0xFF && ((s->b_buffer[i+1] & 0xE0) == 0xE0)) { len = mp_get_mp3_header(&(s->b_buffer[i]), &chans, &srate, &spf, &layer, NULL); if(len > 0 && (srate == s->wf->nSamplesPerSec) && (i + len <= s->b_buffer_len)) { score[layer]++; i += len; } } i++; } max = 0; layer = 2; for(i = 1; i <= 3; i++) { if(score[i] >= max) { max = score[i]; layer = i; } } return layer; //actual layer with the highest score}extern int aac_parse_frame(uint8_t *buf, int *srate, int *num);static int parse_audio(muxer_stream_t *s, int finalize, unsigned int *nf, double *timer, double delay, int drop){ int i, j, len, chans, srate, spf, layer, dummy, tot, num, frm_idx; int finished; unsigned int frames; uint64_t idur; double dur; muxer_headers_t *spriv = (muxer_headers_t *) s->priv; i = tot = frames = 0; finished = 0; while(1) { len = 0; switch(s->wf->wFormatTag) { case AUDIO_MP2: case AUDIO_MP3: { if(i + 3 >= s->b_buffer_len) { finished = 1; break; } if(s->b_buffer[i] == 0xFF && ((s->b_buffer[i+1] & 0xE0) == 0xE0)) { len = mp_get_mp3_header(&(s->b_buffer[i]), &chans, &srate, &spf, &layer, NULL); if(len > 0 && (srate == s->wf->nSamplesPerSec) && (i + len <= s->b_buffer_len) && layer == spriv->mpa_layer) { dur = (double) spf / (double) srate; idur = (27000000ULL * spf) / srate; } else len = 0; } } break; case AUDIO_A52: { if(i + 6 >= s->b_buffer_len) { finished = 1; break; } if(s->b_buffer[i] == 0x0B && s->b_buffer[i+1] == 0x77) { srate = 0; #ifdef USE_LIBA52 len = a52_syncinfo(&(s->b_buffer[i]), &dummy, &srate, &dummy); #else len = mp_a52_framesize(&(s->b_buffer[i]), &srate); #endif if((len > 0) && (srate == s->wf->nSamplesPerSec) && (i + len <= s->b_buffer_len)) { dur = (double) 1536 / (double) srate; idur = (27000000ULL * 1536) / srate; } else len = 0; } } break; case AUDIO_AAC1: case AUDIO_AAC2: { if(i + 7 >= s->b_buffer_len) { finished = 1; break; } if(s->b_buffer[i] == 0xFF && ((s->b_buffer[i+1] & 0xF6) == 0xF0)) { len = aac_parse_frame(&(s->b_buffer[i]), &srate, &num); if((len > 0) && (srate == s->wf->nSamplesPerSec) && (i + len <= s->b_buffer_len)) { dur = (double) 1024 / (double) srate; idur = (27000000ULL * 1024 * num) / srate; } else len = 0; } } } if(finished) break; if(!len) { i++; continue; } spriv->timer += dur; if(spriv->drop_delayed_frames && delay < 0 && spriv->timer <= -delay) { i += len; tot = i; continue; } frames++; fill_last_frame(spriv, &(s->b_buffer[tot]), i - tot); frm_idx = add_frame(spriv, idur, &(s->b_buffer[i]), len, 0, spriv->last_pts, spriv->last_pts); if(frm_idx < 0) { mp_msg(MSGT_MUXER, MSGL_FATAL, "Couldn't add audio frame buffer(frame), abort\n"); goto audio_exit; } for(j = frm_idx; j < spriv->framebuf_cnt; j++) spriv->framebuf[j].pts = spriv->last_pts; spriv->last_pts += idur; i += len; tot = i; }audio_exit: if(tot) { memmove(s->b_buffer, &(s->b_buffer[tot]), s->b_buffer_len - tot); s->b_buffer_len -= tot; s->b_buffer_ptr += tot; if(s->b_buffer_len > 0) memmove(s->b_buffer, &(s->b_buffer[s->b_buffer_ptr]), s->b_buffer_len); s->b_buffer_ptr = 0; } if(finalize) { frm_idx = add_frame(spriv, 0, s->b_buffer, s->b_buffer_len, 0, spriv->last_pts, spriv->last_pts); if(frm_idx >= 0) { for(j = frm_idx; j < spriv->framebuf_cnt; j++) spriv->framebuf[j].pts = spriv->last_pts; } } *nf = frames; *timer = spriv->timer; return tot;}static void fix_parameters(muxer_stream_t *stream){ muxer_headers_t *spriv = stream->priv; muxer_t *muxer = stream->muxer; muxer_priv_t *priv = muxer->priv; if(stream->type == MUXER_TYPE_AUDIO) { spriv->is_ready = 1; if(conf_abuf_size) spriv->max_buffer_size = conf_abuf_size*1024; else spriv->max_buffer_size = 4*1024; if(stream->wf->wFormatTag == AUDIO_A52) { stream->ckid = be2me_32 (0x1bd); if(priv->is_genmpeg1 || priv->is_genmpeg2) fix_audio_sys_header(priv, spriv->id, 0xbd, FFMAX(conf_abuf_size, 58)*1024); //only one audio at the moment spriv->id = 0xbd; if(!conf_abuf_size) spriv->max_buffer_size = 16*1024; } else if(stream->wf->wFormatTag == AUDIO_AAC1 || stream->wf->wFormatTag == AUDIO_AAC2) { priv->use_psm = 1; } else if(stream->wf->wFormatTag == AUDIO_MP2 || stream->wf->wFormatTag == AUDIO_MP3) spriv->is_ready = 0; } else //video { if(conf_vbuf_size) spriv->max_buffer_size = conf_vbuf_size*1024; else { if(priv->is_dvd) spriv->max_buffer_size = 232*1024; else if(priv->is_xsvcd) spriv->max_buffer_size = 230*1024; else if(priv->is_xvcd) spriv->max_buffer_size = 46*1024; else spriv->max_buffer_size = 232*1024; //no profile => unconstrained :) FIXME!!! } if(is_mpeg4(stream->bih->biCompression)) spriv->is_ready = 0; else spriv->is_ready = 1; }}static void mpegfile_write_chunk(muxer_stream_t *s,size_t len,unsigned int flags, double dts_arg, double pts_arg){ size_t sz = 0; uint64_t tmp; muxer_t *muxer = s->muxer; muxer_priv_t *priv = (muxer_priv_t *)muxer->priv; muxer_headers_t *spriv = (muxer_headers_t*) s->priv; float fps; uint32_t stream_format, nf; if(s->buffer == NULL) return; if(len == -1) return; if (s->type == MUXER_TYPE_VIDEO) { // try to recognize frame type... fps = (float) s->h.dwRate/ (float) s->h.dwScale; spriv->type = 1; stream_format = s->bih->biCompression; if(! spriv->vframes) { spriv->last_dts = spriv->last_pts - (uint64_t)(27000000.0f/fps); mp_msg(MSGT_MUXER, MSGL_INFO,"INITV: %.3lf, %.3lf, fps: %.3f\r\n", (double) spriv->last_pts/27000000.0f, (double) spriv->last_dts/27000000.0f, fps); } if(is_mpeg1(stream_format) || is_mpeg2(stream_format)) { spriv->is_mpeg12 = 1; spriv->is_ready = 1; if(len) sz = parse_mpeg12_video(s, priv, spriv, fps, len); else { tmp = (uint64_t) (27000000.0f / fps); spriv->last_pts += tmp; spriv->last_dts += tmp; } } else if(is_mpeg4(stream_format)) { spriv->is_mpeg12 = 0; spriv->telecine = 0; if(spriv->size == 0) priv->use_psm = 1; if(len) sz = parse_mpeg4_video(s, priv, spriv, fps, len); else { tmp = (uint64_t) (27000000.0f / fps); spriv->last_pts += tmp; spriv->last_dts += tmp; } } mp_msg(MSGT_MUXER, MSGL_DBG2,"mpegfile_write_chunk, Video codec=%x, len=%u, mpeg12 returned %u\n", stream_format, (uint32_t) len, (uint32_t) sz); } else { // MUXER_TYPE_AUDIO double fake_timer; spriv->type = 0; stream_format = s->wf->wFormatTag; if(s->b_buffer_size - s->b_buffer_len < len) { if(s->b_buffer_len > SIZE_MAX - len) { mp_msg(MSGT_MUXER, MSGL_FATAL, "\nFATAL! couldn't realloc, integer overflow\n"); return; } s->b_buffer = realloc(s->b_buffer, len + s->b_buffer_len); if(s->b_buffer == NULL) { mp_msg(MSGT_MUXER, MSGL_FATAL, "\nFATAL! couldn't realloc %d bytes\n", len + s->b_buffer_len); return; } s->b_buffer_size = len + s->b_buffer_len; mp_msg(MSGT_MUXER, MSGL_DBG2, "REALLOC(%d) bytes to AUDIO backbuffer\n", s->b_buffer_size); } memcpy(&(s->b_buffer[s->b_buffer_ptr + s->b_buffer_len]), s->buffer, len); s->b_buffer_len += len; if(!spriv->is_ready) { if(s->b_buffer_len >= 32*1024) { spriv->mpa_layer = analyze_mpa(s); spriv->is_ready = 1; } } else { parse_audio(s, 0, &nf, &fake_timer, priv->init_adelay, priv->drop); spriv->vframes += nf; if(! spriv->vframes) mp_msg(MSGT_MUXER, MSGL_INFO, "AINIT: %.3lf\r\n", (double) spriv->last_pts/27000000.0f); } } if(spriv->psm_fixed == 0) { add_to_psm(priv, spriv->id, stream_format); spriv->psm_fixed = 1; priv->psm_streams_cnt++; if((priv->psm_streams_cnt == muxer->num_videos + muxer->num_audios) && priv->use_psm) write_psm_block(muxer, muxer->stream); } flush_buffers(muxer, 0);}static void mpegfile_write_index(muxer_t *muxer){ int i, nf; double fake_timer; muxer_priv_t *priv = (muxer_priv_t *) muxer->priv; mp_msg(MSGT_MUXER, MSGL_INFO, MSGTR_WritingTrailer); for(i = 0; i < muxer->avih.dwStreams; i++) { if(muxer->streams[i]->type == MUXER_TYPE_AUDIO) parse_audio(muxer->streams[i], 1, &nf, &fake_timer, priv->init_adelay, priv->drop); } while(flush_buffers(muxer, 0) > 0); flush_buffers(muxer, 1); if(priv->is_genmpeg1 || priv->is_genmpeg2) { priv->scr = 0; write_mpeg_pack(muxer, NULL, muxer->stream, 1); //insert fake Nav Packet } mp_msg(MSGT_MUXER, MSGL_INFO, "\nOverhead: %.3lf%% (%"PRIu64" / %"PRIu64")\n", 100.0 * (double)priv->headers_size / (double)priv->data_size, priv->headers_size, priv->data_size);}static void mpegfile_write_header(muxer_t *muxer){ muxer_priv_t *priv = (muxer_priv_t*) muxer->priv; mp_msg(MSGT_MUXER, MSGL_INFO, MSGTR_WritingHeader); priv->headers_cnt++; //write the first system header only for generic mpeg1/2 muxes, and only when we have collected all necessary infos if(priv->is_genmpeg1 || priv->is_genmpeg2 || ((priv->is_xvcd || priv->is_xsvcd) && (priv->headers_cnt == 1))) { write_mpeg_pack(muxer, NULL, muxer->stream, 0); priv->update_system_header = 0; } return;}static void setup_sys_params(muxer_priv_t *priv){ if(priv->is_dvd) { int v = (conf_vbuf_size ? conf_vbuf_size : 232); int a1 = (conf_abuf_size ? conf_abuf_size : 4); int a2 = (conf_abuf_size>58 ? conf_abuf_size : 58); priv->sys_info.cnt = 4; priv->sys_info.streams[0].id = 0xb9; priv->sys_info.streams[0].type = 1; priv->sys_info.streams[0].bufsize = v*1024; priv->sys_info.streams[1].id = 0xb8; priv->sys_info.streams[1].type = 0; priv->sys_info.streams[1].bufsize = a1*1024; priv->sys_info.streams[2].id = 0xbd; priv->sys_info.streams[2].type = 1; priv->sys_info.streams[2].bufsize = a2*1024; priv->sys_info.streams[3].id = 0xbf; priv->sys_info.streams[3].type = 1; priv->sys_info.streams[3].bufsize = 2*1024; } else if(priv->is_xvcd || priv->is_xsvcd) { int v = (conf_vbuf_size ? conf_vbuf_size : (priv->is_xvcd ? 46: 230)); int a1 = (conf_abuf_size ? conf_abuf_size : 4); priv->sys_info.cnt = 2; priv->sys_info.streams[0].id = 0xe0; priv->sys_info.streams[0].type = 1; priv->sys_info.streams[0].bufsize = v*1024; priv->sys_info.streams[1].id = 0xc0; priv->sys_info.streams[1].type = 0; priv->sys_info.streams[1].bufsize = a1*1024; } else priv->sys_info.cnt = 0;}/* excerpt from DGPulldown Copyright (C) 2005-2006, Donald Graft */static void generate_flags(int source, int target){ unsigned int i, trfp; uint64_t dfl,tfl; unsigned char ormask[4] = {0x0, 0x2, 0x80, 0x82}; dfl = (target - source) << 1; tfl = source >> 1; trfp = 0; for(i = 0; i < MAX_PATTERN_LENGTH; i++) { tfl += dfl; if(tfl >= source) { tfl -= source; bff_mask[i] = ormask[trfp + 1]; trfp ^= 2; } else bff_mask[i] = ormask[trfp]; }}int muxer_init_muxer_mpeg(muxer_t *muxer){ muxer_priv_t *priv; priv = (muxer_priv_t *) calloc(1, sizeof(muxer_priv_t)); if(priv == NULL) return 0; priv->update_system_header = 1; //calloc() already zero-ed all flags, so we assign only the ones we need if(conf_mux != NULL) { if(! strcasecmp(conf_mux, "mpeg1")) { priv->mux = MUX_MPEG1; priv->packet_size = 2048; priv->is_genmpeg1 = 1; priv->muxrate = 1800 * 125; //Constrained parameters }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?