當(dāng)前位置:首頁 > 芯聞號 > 充電吧
[導(dǎo)讀]雜記asla-lib庫函數(shù)snd_pcm_open打開流程淺析ac97聲卡intel8x0的DMA內(nèi)存substream->dma_buffer什么時候被賦值淺析ac97聲卡intel8x0的r

雜記asla-lib庫函數(shù)snd_pcm_open打開流程
淺析ac97聲卡intel8x0的DMA內(nèi)存substream->dma_buffer什么時候被賦值
淺析ac97聲卡intel8x0的runtime->dma_area是怎么獲取的
淺析ac97聲卡intel8x0的pci總線DMA物理地址填充和音頻數(shù)據(jù)發(fā)送流程
aplay.c
==> main
==> snd_pcm_open(&handle, pcm_name, stream, open_mode); // 打開一路pcm,刷新config配置
如果是"default",同時type等于SND_CONFIG_TYPE_COMPOUND那么這里對應(yīng)"empty"
static const char *const build_in_pcms[] = {
??? "adpcm", "alaw", "copy", "dmix", "file", "hooks", "hw", "ladspa", "lfloat",
??? "linear", "meter", "mulaw", "multi", "null", "empty", "plug", "rate", "route", "share",
??? "shm", "dsnoop", "dshare", "asym", "iec958", "softvol", "mmap_emul",
??? NULL
};
_snd_pcm_empty_open和snd_pcm_open_named_slave
==> snd_pcm_open_conf(pcmp, name, root, conf, stream, mode);
==> open_func = snd_dlobj_cache_lookup(open_name);將獲得lib庫中_snd_pcm_empty_open函數(shù)
??? 所以open_func將等于_snd_pcm_empty_open
???
??? _snd_pcm_empty_open
??? _snd_pcm_asym_open
??? _snd_pcm_plug_open
??? _snd_pcm_softvol_open
??? _snd_pcm_dmix_open
??? _snd_pcm_hw_open
??? ==> snd_pcm_hw_open(pcmp, name, card, device, subdevice, stream,
??? ??? ??? ????? mode | (nonblock ? SND_PCM_NONBLOCK : 0),
??? ??? ??? ????? 0, sync_ptr_ioctl);

==> snd_ctl_hw_open
filename等于"/dev/snd/controlC0"
==> snd_open_device(filename, fmode);
??? ctl->ops = &snd_ctl_hw_ops;
??? ctl->private_data = hw;
??? ctl->poll_fd = fd;
??? *handle = ctl;
filename等于"/dev/snd/pcmC0D0p"
==> fd = snd_open_device(filename, fmode);
==> return snd_pcm_hw_open_fd(pcmp, name, fd, 0, sync_ptr_ioctl);
==> snd_pcm_new(&pcm, SND_PCM_TYPE_HW, name, info.stream, mode);
??? pcm->ops = &snd_pcm_hw_ops;
??? pcm->fast_ops = &snd_pcm_hw_fast_ops;

static int snd_pcm_hw_mmap_control(snd_pcm_t *pcm)
{
??? snd_pcm_hw_t *hw = pcm->private_data;
??? void *ptr;
??? int err;
??? if (hw->sync_ptr == NULL) { // 如果還沒有mmap,那么執(zhí)行mmap映射內(nèi)核空間驅(qū)動使用的聲音緩沖區(qū)
??? ??? ptr = mmap(NULL, page_align(sizeof(struct sndrv_pcm_mmap_control)),
??? ??? ??? ?? PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED,
??? ??? ??? ?? hw->fd, SNDRV_PCM_MMAP_OFFSET_CONTROL);
??? ??? if (ptr == MAP_FAILED || ptr == NULL) {
??? ??? ??? err = -errno;
??? ??? ??? SYSMSG("control mmap failed");
??? ??? ??? return err;
??? ??? }
??? ??? hw->mmap_control = ptr; // 聲卡驅(qū)動頭部填充了一個結(jié)構(gòu)體sndrv_pcm_mmap_control,類似qvfb顯示原理.
// struct sndrv_pcm_mmap_control {
//?? sndrv_pcm_uframes_t appl_ptr;??? /* RW: appl ptr (0...boundary-1) */
//?? sndrv_pcm_uframes_t avail_min;??? /* RW: min available frames for wakeup */
// };
??? } else {
??? ??? hw->mmap_control->avail_min = 1;
??? }
??? snd_pcm_set_appl_ptr(pcm, &hw->mmap_control->appl_ptr, hw->fd, SNDRV_PCM_MMAP_OFFSET_CONTROL);
??? return 0;
}

snd_pcm_mmap

??? ??? switch (i->type) {
??? ??? case SND_PCM_AREA_MMAP: // 表示為數(shù)據(jù)區(qū)分配驅(qū)動內(nèi)存,在snd_pcm_hw_channel_info中設(shè)置了type
??? ??? ??? ptr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, i->u.mmap.fd, i->u.mmap.offset);
/*
mmap
==> snd_pcm_mmap_data
==> snd_pcm_default_mmap
// mmap the DMA buffer on RAM
static int snd_pcm_default_mmap(struct snd_pcm_substream *substream,
??? ??? ??? ??? struct vm_area_struct *area)
{
??? area->vm_ops = &snd_pcm_vm_ops_data; // vma操作函數(shù),當(dāng)應(yīng)用程序向該area讀寫不存在的內(nèi)存數(shù)據(jù)時,
??? area->vm_private_data = substream;?? // 將執(zhí)行snd_pcm_vm_ops_data中的fault
??? // 函數(shù)snd_pcm_mmap_data_fault進一步以頁為單位申請內(nèi)存空間,所以如果用戶程序需要64k,那么將執(zhí)行16次,每次申請4k空間[luther.gliethttp].
??? area->vm_flags |= VM_RESERVED;
??? atomic_inc(&substream->mmap_count);
??? return 0;
}
*/
??? ??? ??? if (ptr == MAP_FAILED) {
??? ??? ??? ??? SYSERR("mmap failed");
??? ??? ??? ??? return -errno;
??? ??? ??? }
??? ??? ??? i->addr = ptr;


==> snd_pcm_mmap_control
static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file,
??? ??? ??? ??? struct vm_area_struct *area)
{
??? struct snd_pcm_runtime *runtime;
??? long size;
??? if (!(area->vm_flags & VM_READ))
??? ??? return -EINVAL;
??? runtime = substream->runtime;
??? size = area->vm_end - area->vm_start;
??? if (size != PAGE_ALIGN(sizeof(struct snd_pcm_mmap_control)))
??? ??? return -EINVAL;
??? area->vm_ops = &snd_pcm_vm_ops_control; // 當(dāng)對( area->vm_start,area->vm_end)之間空間操作,發(fā)生
??? area->vm_private_data = substream;????? // 缺頁時,內(nèi)核將調(diào)用該vm_ops方法來處理fault異常,
??? area->vm_flags |= VM_RESERVED;????????? // 進而執(zhí)行snd_pcm_mmap_control_fault申請1個page空間
??? return 0;
}



==> writei_func = snd_pcm_writei;
==> playback(argv[optind++]);
==> playback_go(fd, dtawave, pbrec_count, FORMAT_WAVE, name);
==> pcm_write(audiobuf, l);
==> writei_func(handle, data, count);就是調(diào)用上面的snd_pcm_writei
==> snd_pcm_writei
==> _snd_pcm_writei
==> pcm->fast_ops->writei(pcm->fast_op_arg, buffer, size);
==> snd_pcm_plugin_writei
==> snd_pcm_write_areas(pcm, areas, 0, size,
??? ??? ??? ??? ??????? snd_pcm_plugin_write_areas);
==> avail = snd_pcm_avail_update(pcm); // 獲取可用緩沖區(qū)位置偏移索引值
==> func()就是snd_pcm_plugin_write_areas函數(shù)發(fā)送1024幀音頻數(shù)據(jù),一幀對應(yīng)一次完整采樣,比如stereo立體聲
,24bits量化,那么這里一幀對應(yīng)3*2字節(jié)數(shù)據(jù),即一次完整采樣所需空間[luther.gliethttp].
==> plugin->write(pcm, areas, offset, frames,
??? ??? ??? ??? ?????? slave_areas, slave_offset, &slave_frames);
即調(diào)用snd_pcm_linear_write_areas函數(shù)將areas中的frames頻數(shù)據(jù)拷貝到slave_areas內(nèi)存區(qū)

==> pcm->fast_ops->mmap_commit(pcm->fast_op_arg, offset, frames);
==> snd_pcm_dmix_mmap_commit
==> snd_pcm_dmix_sync_area
/*
?*? synchronize shm ring buffer with hardware
?*/
static void snd_pcm_dmix_sync_area(snd_pcm_t *pcm)
==> /* add sample areas here */
??? src_areas = snd_pcm_mmap_areas(pcm);
??? dst_areas = snd_pcm_mmap_areas(dmix->spcm); // 添加
==> mix_areas(dmix, src_areas, dst_areas, appl_ptr, slave_appl_ptr, transfer);
??? if (dmix->interleaved) { // 可以將緩沖中的音頻數(shù)據(jù)填充到硬件中[luther.gliethttp]
??? ??? /*
??? ??? ?* process all areas in one loop
??? ??? ?* it optimizes the memory accesses for this case
??? ??? ?*/
??? ??? do_mix_areas(size * channels,
??? ??? ??? ???? (unsigned char *)dst_areas[0].addr + sample_size * dst_ofs * channels,
??? ??? ??? ???? (unsigned char *)src_areas[0].addr + sample_size * src_ofs * channels,
??? ??? ??? ???? dmix->u.dmix.sum_buffer + dst_ofs * channels,
??? ??? ??? ???? sample_size,
??? ??? ??? ???? sample_size,
??? ??? ??? ???? sizeof(signed int));
??? ??? return;
??? }
==> do_mix_areas(size * channels,
??? ??? ??? ???? (unsigned char *)dst_areas[0].addr + sample_size * dst_ofs * channels,
??? ??? ??? ???? (unsigned char *)src_areas[0].addr + sample_size * src_ofs * channels,
??? ??? ??? ???? dmix->u.dmix.sum_buffer + dst_ofs * channels,
??? ??? ??? ???? sample_size,
??? ??? ??? ???? sample_size,
??? ??? ??? ???? sizeof(signed int));
這里的do_mix_areas在i386中,使用下面完全用匯編實現(xiàn)的拷貝函數(shù)MIX_AREAS_32完成數(shù)據(jù)從src到dst的快速拷貝,
每拷貝一次,聲卡就會發(fā)出一點聲音[luther.gliethttp]
/*
?*? for plain i386, 32-bit version (24-bit resolution)
?*/
static void MIX_AREAS_32(unsigned int size,
??? ??? ??? ?volatile signed int *dst, signed int *src,
??? ??? ??? ?volatile signed int *sum, size_t dst_step,
??? ??? ??? ?size_t src_step, size_t sum_step)

_snd_pcm_asym_open
_snd_pcm_dmix_open


snd_pcm_plugin_avail_update
==> snd_pcm_avail_update(slave);
==> pcm->fast_ops->avail_update(pcm->fast_op_arg);
==> snd_pcm_dmix_avail_update
==> snd_pcm_mmap_playback_avail(pcm);


alsa_sound_init
#define CONFIG_SND_MAJOR??? 116??? /* standard configuration */
static int major = CONFIG_SND_MAJOR;
module_init(alsa_sound_init)
alsa_sound_init
==> register_chrdev(major, "alsa", &snd_fops)?????????????? // 主設(shè)備號為116的所有設(shè)備都為alsa設(shè)備,節(jié)點方法集為snd_fops
static const struct file_operations snd_fops =????????????? // alsa的設(shè)備名為pcmC0D1c或pcmC0D1p等[luther.gliethttp].
{
??? .owner =??? THIS_MODULE,
??? .open =??????? snd_open
};
snd_open
==> __snd_open(inode, file);
==> __snd_open
??? unsigned int minor = iminor(inode);
??? mptr = snd_minors[minor];
??? file->f_op = fops_get(mptr->f_ops);
??? file->f_op->open(inode, file);
const struct file_operations snd_pcm_f_ops[2] = {
??? {?????????????????????????????????????????????????????? // alsa使用到的SNDRV_PCM_STREAM_PLAYBACK放音方法集[luther.gliethttp]
??????? .owner =??????? THIS_MODULE,
??????? .write =??????? snd_pcm_write,
??????? .aio_write =??????? snd_pcm_aio_write,
??????? .open =??????????? snd_pcm_playback_open,
??????? .release =??????? snd_pcm_release,
??????? .poll =??????????? snd_pcm_playback_poll,
??????? .unlocked_ioctl =??? snd_pcm_playback_ioctl,
??????? .compat_ioctl =???? snd_pcm_ioctl_compat,
??????? .mmap =??????????? snd_pcm_mmap,
??????? .fasync =??????? snd_pcm_fasync,
??????? .get_unmapped_area =??? dummy_get_unmapped_area,
??? },
??? {?????????????????????????????????????????????????????? // alsa使用到的SNDRV_PCM_STREAM_CAPTURE錄音方法集[luther.gliethttp]
??????? .owner =??????? THIS_MODULE,
??????? .read =??????????? snd_pcm_read,
??????? .aio_read =??????? snd_pcm_aio_read,
??????? .open =??????????? snd_pcm_capture_open,
??????? .release =??????? snd_pcm_release,
??????? .poll =??????????? snd_pcm_capture_poll,
??????? .unlocked_ioctl =??? snd_pcm_capture_ioctl,
??????? .compat_ioctl =???? snd_pcm_ioctl_compat,
??????? .mmap =??????????? snd_pcm_mmap,
??????? .fasync =??????? snd_pcm_fasync,
??????? .get_unmapped_area =??? dummy_get_unmapped_area,
??? }
};
=========================================================================
snd_intel8x0_probe
==> snd_intel8x0_create
==> request_irq(pci->irq, snd_intel8x0_interrupt, IRQF_SHARED,
card->shortname, chip)
snd_intel8x0_interrupt
snd_intel8x0_update


snd_open
==> snd_pcm_playback_open
==> snd_pcm_open
==> snd_pcm_open_file
==> snd_pcm_open_substream
==> substream->ops->open(substream)即snd_intel8x0_playback_ops.open
==> snd_intel8x0_playback_open
==> snd_intel8x0_pcm_open
static int snd_intel8x0_pcm_open(struct snd_pcm_substream *substream, struct ichdev *ichdev)
{
??? struct intel8x0 *chip = snd_pcm_substream_chip(substream);
??? struct snd_pcm_runtime *runtime = substream->runtime;
??? int err;

??? ichdev->substream = substream;
??? runtime->hw = snd_intel8x0_stream; // 聲卡配置硬件信息[luther.gliethttp]
??? runtime->hw.rates = ichdev->pcm->rates;
??? snd_pcm_limit_hw_rates(runtime);
??? if (chip->device_type == DEVICE_SIS) {
??? ??? runtime->hw.buffer_bytes_max = 64*1024;
??? ??? runtime->hw.period_bytes_max = 64*1024;
??? }
??? if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
??? ??? return err;
??? runtime->private_data = ichdev;
??? return 0;
}

ioctl(SNDRV_PCM_IOCTL_HW_PARAMS)
==> snd_pcm_f_ops.unlocked_ioctl即:snd_pcm_playback_ioctl
==> snd_pcm_playback_ioctl
==> snd_pcm_playback_ioctl1
==> snd_pcm_common_ioctl1
??? case SNDRV_PCM_IOCTL_HW_PARAMS:
??? ??? return snd_pcm_hw_params_user(substream, arg);
==> snd_pcm_hw_params_user
==> snd_pcm_hw_params
==> substream->ops->hw_params即snd_intel8x0_playback_ops.hw_params
==> snd_intel8x0_hw_params
==> snd_ac97_pcm_open(ichdev->pcm, params_rate(hw_params),
??? ??? ??? ??? params_channels(hw_params),
??? ??? ??? ??? ichdev->pcm->r[dbl].slots);


ioctl(SNDRV_PCM_IOCTL_PREPARE)
==> snd_pcm_playback_ioctl
==> snd_pcm_playback_ioctl1
==> snd_pcm_common_ioctl1
==> snd_pcm_prepare // prepare the PCM substream to be triggerable
==> snd_pcm_action_nonatomic(&snd_pcm_action_prepare,
??? ??? ??? ??? ??? ?????? substream, f_flags);
==> snd_pcm_action_single(ops, substream, state);
??? ops->pre_action(substream, state);
??? ops->do_action(substream, state);
??? ops->post_action(substream, state);
??? 上面ops就是之前提到的snd_pcm_action_prepare
==> snd_pcm_do_prepare調(diào)用snd_pcm_do_reset(substream, 0);復(fù)位
??? substream->ops->prepare(substream);即snd_intel8x0_playback_ops.prepare
==> snd_intel8x0_pcm_prepare
static int snd_intel8x0_pcm_prepare(struct snd_pcm_substream *substream)
{
??? struct intel8x0 *chip = snd_pcm_substream_chip(substream);
??? struct snd_pcm_runtime *runtime = substream->runtime;
??? struct ichdev *ichdev = get_ichdev(substream);
《淺析ac97聲卡intel8x0的runtime->dma_area是怎么獲取的》
??? ichdev->physbuf = runtime->dma_addr;??? // dma緩沖區(qū)地址
??? ichdev->size = snd_pcm_lib_buffer_bytes(substream); // 將幀緩沖大小轉(zhuǎn)為字節(jié)空間大小[luther.gliethttp]
??? ichdev->fragsize = snd_pcm_lib_period_bytes(substream);
??? if (ichdev->ichd == ICHD_PCMOUT) {
??? ??? snd_intel8x0_setup_pcm_out(chip, runtime); // 為play模式設(shè)置ac97寄存器[luther.gliethttp]
??? ??? if (chip->device_type == DEVICE_INTEL_ICH4)
??? ??? ??? ichdev->pos_shift = (runtime->sample_bits > 16) ? 2 : 1;
??? }
??? snd_intel8x0_setup_periods(chip, ichdev); // 設(shè)置PCI總線ac97的bank地址空間[luther.gliethttp]
??? return 0;
}
==> snd_intel8x0_setup_pcm_out
static void snd_intel8x0_setup_pcm_out(struct intel8x0 *chip,
??? ??? ??? ??? ?????? struct snd_pcm_runtime *runtime)
{
??? unsigned int cnt;
??? int dbl = runtime->rate > 48000;
// 一共有如下幾種設(shè)備:enum { DEVICE_INTEL, DEVICE_INTEL_ICH4, DEVICE_SIS, DEVICE_ALI, DEVICE_NFORCE };
??? spin_lock_irq(&chip->reg_lock);
??? switch (chip->device_type) {
??? case DEVICE_ALI:
??? ??? cnt = igetdword(chip, ICHREG(ALI_SCR));
??? ??? cnt &= ~ICH_ALI_SC_PCM_246_MASK;
??? ??? if (runtime->channels == 4 || dbl)
??? ??? ??? cnt |= ICH_ALI_SC_PCM_4;
??? ??? else if (runtime->channels == 6)
??? ??? ??? cnt |= ICH_ALI_SC_PCM_6;
??? ??? iputdword(chip, ICHREG(ALI_SCR), cnt);
??? ??? break;
??? case DEVICE_SIS:
??? ??? cnt = igetdword(chip, ICHREG(GLOB_CNT));
??? ??? cnt &= ~ICH_SIS_PCM_246_MASK;
??? ??? if (runtime->channels == 4 || dbl)
??? ??? ??? cnt |= ICH_SIS_PCM_4;
??? ??? else if (runtime->channels == 6)
??? ??? ??? cnt |= ICH_SIS_PCM_6;
??? ??? iputdword(chip, ICHREG(GLOB_CNT), cnt);
??? ??? break;
??? default:
??? ??? cnt = igetdword(chip, ICHREG(GLOB_CNT));
??? ??? cnt &= ~(ICH_PCM_246_MASK | ICH_PCM_20BIT);
??? ??? if (runtime->channels == 4 || dbl)
??? ??? ??? cnt |= ICH_PCM_4;
??? ??? else if (runtime->channels == 6)
??? ??? ??? cnt |= ICH_PCM_6;
??? ??? else if (runtime->channels == 8)
??? ??? ??? cnt |= ICH_PCM_8;
??? ??? if (chip->device_type == DEVICE_NFORCE) {
??? ??? ??? /* reset to 2ch once to keep the 6 channel data in alignment,
??? ??? ??? ?* to start from Front Left always
??? ??? ??? ?*/
??? ??? ??? if (cnt & ICH_PCM_246_MASK) {
??? ??? ??? ??? iputdword(chip, ICHREG(GLOB_CNT), cnt & ~ICH_PCM_246_MASK);
??? ??? ??? ??? spin_unlock_irq(&chip->reg_lock);
??? ??? ??? ??? msleep(50); /* grrr... */
??? ??? ??? ??? spin_lock_irq(&chip->reg_lock);
??? ??? ??? }
??? ??? } else if (chip->device_type == DEVICE_INTEL_ICH4) {
??? ??? ??? if (runtime->sample_bits > 16)
??? ??? ??? ??? cnt |= ICH_PCM_20BIT;
??? ??? }
??? ??? iputdword(chip, ICHREG(GLOB_CNT), cnt);
??? ??? break;
??? }
??? spin_unlock_irq(&chip->reg_lock);
}

ioctl(SNDRV_PCM_IOCTL_START)
==> snd_pcm_playback_ioctl
==> snd_pcm_playback_ioctl1
==> snd_pcm_common_ioctl1
==> snd_pcm_action_lock_irq(&snd_pcm_action_start, substream, SNDRV_PCM_STATE_RUNNING);
==> snd_pcm_action_single // state等于SNDRV_PCM_STATE_RUNNING
static struct action_ops snd_pcm_action_start = {
??? .pre_action = snd_pcm_pre_start,
??? .do_action = snd_pcm_do_start,
??? .undo_action = snd_pcm_undo_start,
??? .post_action = snd_pcm_post_start
};
??? ops->pre_action(substream, state);
??? ops->do_action(substream, state);
??? ops->post_action(substream, state);
??? 上面ops就是之前提到的snd_pcm_action_start
==> snd_pcm_do_start
==> substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);即snd_intel8x0_playback_ops.trigger
==> snd_intel8x0_pcm_trigger啟動ac97數(shù)據(jù)傳輸

以上都只是執(zhí)行一次[luther.gliethttp]
只要發(fā)送音頻數(shù)據(jù),就會執(zhí)行該ioctl更新pointer
ioctl(SNDRV_PCM_IOCTL_HWSYNC)
==> snd_pcm_playback_ioctl
==> snd_pcm_playback_ioctl1
==> snd_pcm_common_ioctl1
==> snd_pcm_hwsync
??? case SNDRV_PCM_STATE_RUNNING:
??????? if ((err = snd_pcm_update_hw_ptr(substream)) < 0)
??? ??? ??? break;
==> snd_pcm_update_hw_ptr
==> snd_pcm_update_hw_ptr_post
==> snd_pcm_update_hw_ptr_pos
==> substream->ops->pointer(substream);即snd_intel8x0_playback_ops.pointer
==> snd_intel8x0_pcm_pointer // 更新dma緩沖區(qū)數(shù)據(jù)最后可用數(shù)據(jù)索引值[luther.gliethttp]

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險,如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉