#include <stdio.h>
#include <stdlib.h>
#include <gpac/isomedia.h>
#include <gpac/internal/isomedia_dev.h>
#include <gpac/media_tools.h>
#include <gpac/constants.h>
#include "def.h"
#include "bits.h"
#include "misc.h"
#include "writemp4.h"
static void write_sample(GF_ISOSample *smp, GF_AVCConfig *avccfg, GF_M4ADecSpecInfo *acfg, u32 is_aac, u32 aac_type, GF_BitStream *bs)
{
if (!avccfg) {
if (is_aac) {
gf_bs_write_int(bs, 0xFFF, 12);
gf_bs_write_int(bs, is_aac == 1 ? 1 : 0, 1);
gf_bs_write_int(bs, 0, 2);
gf_bs_write_int(bs, 1, 1);
gf_bs_write_int(bs, aac_type, 2);
gf_bs_write_int(bs, acfg->base_sr_index, 4);
gf_bs_write_int(bs, 0, 1);
gf_bs_write_int(bs, acfg->nb_chan, 3);
gf_bs_write_int(bs, 0, 4);
gf_bs_write_int(bs, 7 + smp->dataLength, 13);
gf_bs_write_int(bs, 0x7FF, 11);
gf_bs_write_int(bs, 0, 2);
}
gf_bs_write_data(bs, smp->data, smp->dataLength);
} else {
u32 j, nal_size, remain = smp->dataLength;
u8 *ptr = smp->data;
while (remain) {
nal_size = 0;
for (j = 0; j < avccfg->nal_unit_size; j++) {
nal_size |= *ptr;
if (j + 1 < avccfg->nal_unit_size) nal_size <<= 8;
remain--;
ptr++;
}
gf_bs_write_u32(bs, 1);
if (nal_size > smp->dataLength || nal_size == 0) {
gf_bs_write_data(bs, ptr, remain);
remain = 0;
} else {
gf_bs_write_data(bs, ptr, nal_size);
ptr += nal_size;
remain -= nal_size;
}
}
}
}
static int write_raw(GF_ISOFile *fi, u32 hint, u32 data, char *fn, data_t *D, MODE mode)
{
GF_DecoderConfig *dcfg = 0;
GF_M4VDecSpecInfo dsi = { 0 };
GF_M4ADecSpecInfo acfg = { 0 };
GF_AVCConfig *avccfg = 0;
GF_BitStream *bs, *bs_tmp;
GF_ISOSample *smp = 0, *tmp = 0;
GF_HintSample *hint_smp;
GF_RTPPacket *pck;
FILE *fo;
char *pdsi = 0;
u32 i, j, k, l, h, is_aac = 0, aac_type = 0;
u32 di, count, packets, samples, last_smp = 0, m_stype, dsi_size = 0;
m_stype = gf_isom_get_media_subtype(fi, data, 1);
if (m_stype == GF_ISOM_SUBTYPE_MPEG4 || m_stype == GF_ISOM_SUBTYPE_MPEG4_CRYP)
dcfg = gf_isom_get_decoder_config(fi, data, 1);
if (dcfg) {
switch (dcfg->streamType) {
case GF_STREAM_VISUAL:
switch (dcfg->objectTypeIndication) {
case 0x20:
pdsi = dcfg->decoderSpecificInfo->data;
dsi_size = dcfg->decoderSpecificInfo->dataLength;
gf_m4v_get_config(pdsi, dsi_size, &dsi);
break;
case 0x21:
avccfg = gf_isom_avc_config_get(fi, data, 1);
break;
default:
gf_odf_desc_del((GF_Descriptor *) dcfg);
return 0;
}
break;
case GF_STREAM_AUDIO:
switch (dcfg->objectTypeIndication) {
case 0x66:
case 0x67:
case 0x68:
pdsi = dcfg->decoderSpecificInfo->data;
dcfg->decoderSpecificInfo->data = NULL;
dsi_size = dcfg->decoderSpecificInfo->dataLength;
is_aac = 1;
aac_type = dcfg->objectTypeIndication - 0x66;
break;
case 0x40:
pdsi = dcfg->decoderSpecificInfo->data;
dcfg->decoderSpecificInfo->data = NULL;
dsi_size = dcfg->decoderSpecificInfo->dataLength;
is_aac = 2;
break;
case 0x69:
case 0x6B:
break;
default:
gf_odf_desc_del((GF_Descriptor *) dcfg);
return 0;
}
break;
default:
gf_odf_desc_del((GF_Descriptor *) dcfg);
return 0;
}
} else {
switch (m_stype) {
case GF_ISOM_SUBTYPE_AVC_H264:
avccfg = gf_isom_avc_config_get(fi, data, 1);
break;
case GF_ISOM_SUBTYPE_3GP_H263: break;
default: return 0;
}
}
if (0 == (fo = fopen(fn, "wb"))) goto O;
bs = gf_bs_from_file(fo, GF_BITSTREAM_WRITE);
if (is_aac) {
gf_m4a_get_config(pdsi, dsi_size, &acfg);
if (is_aac == 2) aac_type = acfg.base_object_type - 1;
free(pdsi);
pdsi = 0;
}
if (pdsi) {
gf_bs_write_data(bs, pdsi, dsi_size);
free(pdsi);
}
if (dcfg) gf_odf_desc_del((GF_Descriptor *)dcfg);
if (avccfg) {
count = gf_list_count(avccfg->sequenceParameterSets);
for (i = 0; i < count; i++) {
GF_AVCConfigSlot *sl = gf_list_get(avccfg->sequenceParameterSets, i);
gf_bs_write_u32(bs, 1);
gf_bs_write_data(bs, sl->data, sl->size);
}
count = gf_list_count(avccfg->pictureParameterSets);
for (i = 0; i < count; i++) {
GF_AVCConfigSlot *sl = gf_list_get(avccfg->pictureParameterSets, i);
gf_bs_write_u32(bs, 1);
gf_bs_write_data(bs, sl->data, sl->size);
}
}
samples = gf_isom_get_sample_count(fi, !(mode & AUDIO) && (mode & FRAME || mode & COMPLETE) ? data : hint);
for (l = 0, i = 0; i < samples; i++) {
if (0 == (smp = gf_isom_get_sample(fi, !(mode & AUDIO) && (mode & FRAME || mode & COMPLETE) ? data : hint, i + 1, &di))) goto S;
if (mode & AUDIO) {
if (!D->F[i].lost) {
hint_smp = gf_isom_hint_sample_new(GF_ISOM_BOX_TYPE_RTP_STSD);
bs_tmp = gf_bs_new(smp->data, smp->dataLength, GF_BITSTREAM_READ);
gf_isom_hint_sample_read(hint_smp, bs_tmp, smp->dataLength);
gf_bs_del(bs_tmp);
packets = gf_list_count(hint_smp->packetTable);
for (j = 0; j < packets; j++, l++) {
pck = gf_list_get(hint_smp->packetTable, j);
count = gf_list_count(pck->DataTable);
for (k = 0; k < count; k++) {
GF_GenericDTE *dte = gf_list_get(pck->DataTable, k);
if (dte->source == 2) {
GF_SampleDTE *sdte = (GF_SampleDTE *)dte;
if (sdte->sampleNumber != last_smp) {
if (last_smp != 0) {
write_sample(tmp, avccfg, &acfg, is_aac, aac_type, bs);
gf_isom_sample_del(&tmp);
}
if (0 == (tmp = gf_isom_get_sample(fi, data, sdte->sampleNumber, 0))) goto S;
last_smp = sdte->sampleNumber;
}
}
}
}
}
}
else if (mode & FRAME || mode & COMPLETE) {
if (D->F[i].lost) {
h = 0;
if (m_stype == 'MPEG') {
if (!dsi.NumBitsTimeIncrement ||
!(h = mark_not_coded(smp->data, smp->dataLength, dsi.NumBitsTimeIncrement)))
goto E;
}
if (m_stype == 'avc1' && i == 0) h = 64;
if (smp->dataLength > 8 + h) {
if (mode & TRUNC) smp->dataLength = 8 + h;
if (mode & FILL) memset(smp->data + 8 + h, 0, smp->dataLength - (8 + h));
}
}
write_sample(smp, avccfg, 0, 0, 0, bs);
gf_isom_sample_del(&smp);
} else {
hint_smp = gf_isom_hint_sample_new(GF_ISOM_BOX_TYPE_RTP_STSD);
bs_tmp = gf_bs_new(smp->data, smp->dataLength, GF_BITSTREAM_READ);
gf_isom_hint_sample_read(hint_smp, bs_tmp, smp->dataLength);
gf_bs_del(bs_tmp);
packets = gf_list_count(hint_smp->packetTable);
for (j = 0; j < packets; j++, l++) {
pck = gf_list_get(hint_smp->packetTable, j);
count = gf_list_count(pck->DataTable);
for (k = 0; k < count; k++) {
GF_GenericDTE *dte = gf_list_get(pck->DataTable, k);
if (dte->source == 2) {
GF_SampleDTE *sdte = (GF_SampleDTE *)dte;
if (sdte->sampleNumber != last_smp) {
if (last_smp != 0) {
if (!D->P[l].lost) write_sample(tmp, avccfg, 0, 0, 0, bs);
gf_isom_sample_del(&tmp);
}
if (0 == (tmp = gf_isom_get_sample(fi, data, sdte->sampleNumber, 0))) goto S;
last_smp = sdte->sampleNumber;
}
if (D->P[l].lost && !(l == 0 && m_stype == 'avc1')) {
if (mode & FILL && sdte->dataLength > 8) {
memset(tmp->data + sdte->byteOffset + 8, 0, sdte->dataLength - 8);
}
}
}
}
}
}
}
if (tmp) write_sample(tmp, avccfg, &acfg, is_aac, aac_type, bs);
gf_isom_sample_del(&tmp);
if (avccfg)
评论3
最新资源